Add contact share approval view.
This commit is contained in:
parent
6e18d84a10
commit
7a9acce504
|
@ -49,6 +49,7 @@
|
|||
34330A5E1E787BD800DF2FB9 /* ElegantIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34330A5D1E787BD800DF2FB9 /* ElegantIcons.ttf */; };
|
||||
34330AA31E79686200DF2FB9 /* OWSProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = 34330AA21E79686200DF2FB9 /* OWSProgressView.m */; };
|
||||
34382266209A4E400094FEB7 /* ApproveContactShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34382265209A4E3F0094FEB7 /* ApproveContactShareViewController.swift */; };
|
||||
3438226A209B63500094FEB7 /* EditContactShareNameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34382269209B63500094FEB7 /* EditContactShareNameViewController.swift */; };
|
||||
34386A51207D0C01009F5D9C /* HomeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34386A4D207D0C01009F5D9C /* HomeViewController.m */; };
|
||||
34386A52207D0C01009F5D9C /* HomeViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 34386A50207D0C01009F5D9C /* HomeViewCell.m */; };
|
||||
34386A54207D271D009F5D9C /* NeverClearView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34386A53207D271C009F5D9C /* NeverClearView.swift */; };
|
||||
|
@ -632,6 +633,7 @@
|
|||
34330AA11E79686200DF2FB9 /* OWSProgressView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSProgressView.h; sourceTree = "<group>"; };
|
||||
34330AA21E79686200DF2FB9 /* OWSProgressView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSProgressView.m; sourceTree = "<group>"; };
|
||||
34382265209A4E3F0094FEB7 /* ApproveContactShareViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ApproveContactShareViewController.swift; path = SignalMessaging/attachments/ApproveContactShareViewController.swift; sourceTree = SOURCE_ROOT; };
|
||||
34382269209B63500094FEB7 /* EditContactShareNameViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EditContactShareNameViewController.swift; path = SignalMessaging/attachments/EditContactShareNameViewController.swift; sourceTree = SOURCE_ROOT; };
|
||||
34386A4D207D0C01009F5D9C /* HomeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HomeViewController.m; sourceTree = "<group>"; };
|
||||
34386A4E207D0C01009F5D9C /* HomeViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HomeViewCell.h; sourceTree = "<group>"; };
|
||||
34386A4F207D0C01009F5D9C /* HomeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HomeViewController.h; sourceTree = "<group>"; };
|
||||
|
@ -1602,6 +1604,7 @@
|
|||
344F2498200FD03200CFB4F4 /* AttachmentApprovalViewController.swift */,
|
||||
344F248220069E9B00CFB4F4 /* CountryCodeViewController.h */,
|
||||
344F248320069E9B00CFB4F4 /* CountryCodeViewController.m */,
|
||||
34382269209B63500094FEB7 /* EditContactShareNameViewController.swift */,
|
||||
346129DC1FD5C02900532771 /* LockInteractionController.h */,
|
||||
346129DD1FD5C02900532771 /* LockInteractionController.m */,
|
||||
344F2496200FD03200CFB4F4 /* MessageApprovalViewController.swift */,
|
||||
|
@ -3098,6 +3101,7 @@
|
|||
451F8A481FD715BA005CB9DA /* OWSContactAvatarBuilder.m in Sources */,
|
||||
34382266209A4E400094FEB7 /* ApproveContactShareViewController.swift in Sources */,
|
||||
4503F1C3204711D300CEE724 /* OWS107LegacySounds.m in Sources */,
|
||||
3438226A209B63500094FEB7 /* EditContactShareNameViewController.swift in Sources */,
|
||||
346129A61FD1F09100532771 /* OWSContactsManager.m in Sources */,
|
||||
4598198F204E2F28009414F2 /* OWS108CallLoggingPreference.m in Sources */,
|
||||
346129D21FD2085A00532771 /* CommonStrings.swift in Sources */,
|
||||
|
|
|
@ -14,7 +14,7 @@ class TappableView: UIView {
|
|||
|
||||
// MARK: - Initializers
|
||||
|
||||
@available(*, unavailable, message: "use init(call:) constructor instead.")
|
||||
@available(*, unavailable, message: "use other constructor instead.")
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("Unimplemented")
|
||||
}
|
||||
|
|
|
@ -445,6 +445,21 @@
|
|||
/* Label for the 'street' field of a contact's address. */
|
||||
"CONTACT_FIELD_ADDRESS_STREET" = "Street";
|
||||
|
||||
/* Label for the 'family name' field of a contact. */
|
||||
"CONTACT_FIELD_FAMILY_NAME" = "Family Name";
|
||||
|
||||
/* Label for the 'given name' field of a contact. */
|
||||
"CONTACT_FIELD_GIVEN_NAME" = "Given Name";
|
||||
|
||||
/* Label for the 'middle name' field of a contact. */
|
||||
"CONTACT_FIELD_MIDDLE_NAME" = "Middle Name";
|
||||
|
||||
/* Label for the 'name prefix' field of a contact. */
|
||||
"CONTACT_FIELD_NAME_PREFIX" = "Prefix";
|
||||
|
||||
/* Label for the 'name suffix' field of a contact. */
|
||||
"CONTACT_FIELD_NAME_SUFFIX" = "Suffix";
|
||||
|
||||
/* Label for a contact's phone number. */
|
||||
"CONTACT_PHONE" = "Phone";
|
||||
|
||||
|
@ -460,6 +475,9 @@
|
|||
/* Title for the 'Approve contact share' view. */
|
||||
"CONTACT_SHARE_APPROVAL_VIEW_TITLE" = "Share Contact";
|
||||
|
||||
/* Title for the 'edit contact share name' view. */
|
||||
"CONTACT_SHARE_EDIT_NAME_VIEW_TITLE" = "Edit Name";
|
||||
|
||||
/* Indicates that a contact has no name. */
|
||||
"CONTACT_WITHOUT_NAME" = "Unnamed Contact";
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ public protocol ApproveContactShareViewControllerDelegate: class {
|
|||
|
||||
class ContactShareField: NSObject {
|
||||
|
||||
var isIncludedFlag = true
|
||||
private var isIncludedFlag = true
|
||||
|
||||
func localizedLabel() -> String {
|
||||
preconditionFailure("This method must be overridden")
|
||||
|
@ -25,9 +25,13 @@ class ContactShareField: NSObject {
|
|||
return isIncludedFlag
|
||||
}
|
||||
|
||||
func setIsIncluded(isIncluded: Bool) {
|
||||
func setIsIncluded(_ isIncluded: Bool) {
|
||||
isIncludedFlag = isIncluded
|
||||
}
|
||||
|
||||
func applyToContact(contact: OWSContact) {
|
||||
preconditionFailure("This method must be overridden")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
@ -45,6 +49,17 @@ class ContactSharePhoneNumber: ContactShareField {
|
|||
override func localizedLabel() -> String {
|
||||
return value.localizedLabel()
|
||||
}
|
||||
|
||||
override func applyToContact(contact: OWSContact) {
|
||||
assert(isIncluded())
|
||||
|
||||
var values = [OWSContactPhoneNumber]()
|
||||
if let oldValues = contact.phoneNumbers {
|
||||
values += oldValues
|
||||
}
|
||||
values.append(value)
|
||||
contact.phoneNumbers = values
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
@ -62,6 +77,17 @@ class ContactShareEmail: ContactShareField {
|
|||
override func localizedLabel() -> String {
|
||||
return value.localizedLabel()
|
||||
}
|
||||
|
||||
override func applyToContact(contact: OWSContact) {
|
||||
assert(isIncluded())
|
||||
|
||||
var values = [OWSContactEmail]()
|
||||
if let oldValues = contact.emails {
|
||||
values += oldValues
|
||||
}
|
||||
values.append(value)
|
||||
contact.emails = values
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
@ -79,6 +105,17 @@ class ContactShareAddress: ContactShareField {
|
|||
override func localizedLabel() -> String {
|
||||
return value.localizedLabel()
|
||||
}
|
||||
|
||||
override func applyToContact(contact: OWSContact) {
|
||||
assert(isIncluded())
|
||||
|
||||
var values = [OWSContactAddress]()
|
||||
if let oldValues = contact.addresses {
|
||||
values += oldValues
|
||||
}
|
||||
values.append(value)
|
||||
contact.addresses = values
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
@ -158,23 +195,25 @@ class ContactShareFieldView: UIView {
|
|||
guard sender.state == .recognized else {
|
||||
return
|
||||
}
|
||||
checkbox.isSelected = !checkbox.isSelected
|
||||
field.setIsIncluded(!field.isIncluded())
|
||||
checkbox.isSelected = field.isIncluded()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
@objc
|
||||
public class ApproveContactShareViewController: OWSViewController {
|
||||
public class ApproveContactShareViewController: OWSViewController, EditContactShareNameViewControllerDelegate {
|
||||
weak var delegate: ApproveContactShareViewControllerDelegate?
|
||||
|
||||
let contactsManager: OWSContactsManager
|
||||
let contactsManager: OWSContactsManager
|
||||
|
||||
let contactShare: OWSContact
|
||||
var contactShare: OWSContact
|
||||
|
||||
var fields = [ContactShareField]()
|
||||
var fieldViews = [ContactShareFieldView]()
|
||||
|
||||
var nameLabel: UILabel!
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
@available(*, unavailable, message:"use other constructor instead.")
|
||||
|
@ -194,7 +233,6 @@ public class ApproveContactShareViewController: OWSViewController {
|
|||
}
|
||||
|
||||
func buildFields() {
|
||||
var fields = [ContactShareField]()
|
||||
var fieldViews = [ContactShareFieldView]()
|
||||
|
||||
// TODO: Avatar
|
||||
|
@ -202,7 +240,6 @@ public class ApproveContactShareViewController: OWSViewController {
|
|||
if let phoneNumbers = contactShare.phoneNumbers {
|
||||
for phoneNumber in phoneNumbers {
|
||||
let field = ContactSharePhoneNumber(phoneNumber)
|
||||
fields.append(field)
|
||||
let fieldView = ContactShareFieldView(field: field, previewViewBlock: { [weak self] _ in
|
||||
guard let strongSelf = self else { return UIView() }
|
||||
return strongSelf.previewView(forPhoneNumber: phoneNumber)
|
||||
|
@ -214,7 +251,6 @@ public class ApproveContactShareViewController: OWSViewController {
|
|||
if let emails = contactShare.emails {
|
||||
for email in emails {
|
||||
let field = ContactShareEmail(email)
|
||||
fields.append(field)
|
||||
let fieldView = ContactShareFieldView(field: field, previewViewBlock: { [weak self] _ in
|
||||
guard let strongSelf = self else { return UIView() }
|
||||
return strongSelf.previewView(forEmail: email)
|
||||
|
@ -226,7 +262,6 @@ public class ApproveContactShareViewController: OWSViewController {
|
|||
if let addresses = contactShare.addresses {
|
||||
for address in addresses {
|
||||
let field = ContactShareAddress(address)
|
||||
fields.append(field)
|
||||
let fieldView = ContactShareFieldView(field: field, previewViewBlock: { [weak self] _ in
|
||||
guard let strongSelf = self else { return UIView() }
|
||||
return strongSelf.previewView(forAddress: address)
|
||||
|
@ -235,7 +270,6 @@ public class ApproveContactShareViewController: OWSViewController {
|
|||
}
|
||||
}
|
||||
|
||||
self.fields = fields
|
||||
self.fieldViews = fieldViews
|
||||
}
|
||||
|
||||
|
@ -290,7 +324,7 @@ public class ApproveContactShareViewController: OWSViewController {
|
|||
if canShareContact() {
|
||||
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: NSLocalizedString("ATTACHMENT_APPROVAL_SEND_BUTTON",
|
||||
comment: "Label for 'send' button in the 'attachment approval' dialog."),
|
||||
style: .plain, target: self, action: #selector(didPressSendButton))
|
||||
style: .plain, target: self, action: #selector(didPressSendButton))
|
||||
} else {
|
||||
self.navigationItem.rightBarButtonItem = nil
|
||||
}
|
||||
|
@ -391,6 +425,7 @@ public class ApproveContactShareViewController: OWSViewController {
|
|||
stackView.axis = .horizontal
|
||||
stackView.alignment = .center
|
||||
stackView.layoutMargins = .zero
|
||||
stackView.spacing = 10
|
||||
row.addSubview(stackView)
|
||||
stackView.autoPinLeadingToSuperviewMargin()
|
||||
stackView.autoPinTrailingToSuperviewMargin()
|
||||
|
@ -398,6 +433,7 @@ public class ApproveContactShareViewController: OWSViewController {
|
|||
stackView.autoPinBottomToSuperviewMargin()
|
||||
|
||||
let nameLabel = UILabel()
|
||||
self.nameLabel = nameLabel
|
||||
nameLabel.text = contactShare.displayName
|
||||
nameLabel.font = UIFont.ows_dynamicTypeBody
|
||||
nameLabel.textColor = UIColor.ows_materialBlue
|
||||
|
@ -518,6 +554,24 @@ public class ApproveContactShareViewController: OWSViewController {
|
|||
|
||||
// MARK: -
|
||||
|
||||
func filteredContactShare() -> OWSContact {
|
||||
let result = self.contactShare.newContact(withNamePrefix: self.contactShare.namePrefix,
|
||||
givenName: self.contactShare.givenName,
|
||||
middleName: self.contactShare.middleName,
|
||||
familyName: self.contactShare.familyName,
|
||||
nameSuffix: self.contactShare.nameSuffix)
|
||||
|
||||
for fieldView in fieldViews {
|
||||
if fieldView.field.isIncluded() {
|
||||
fieldView.field.applyToContact(contact: result)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
func didPressSendButton() {
|
||||
Logger.info("\(logTag) \(#function)")
|
||||
|
||||
|
@ -526,7 +580,10 @@ public class ApproveContactShareViewController: OWSViewController {
|
|||
return
|
||||
}
|
||||
|
||||
delegate.approveContactShare(self, didApproveContactShare: contactShare)
|
||||
let filteredContactShare = self.filteredContactShare()
|
||||
assert(filteredContactShare.ows_isValid())
|
||||
|
||||
delegate.approveContactShare(self, didApproveContactShare: filteredContactShare)
|
||||
}
|
||||
|
||||
func didPressCancel() {
|
||||
|
@ -543,6 +600,17 @@ public class ApproveContactShareViewController: OWSViewController {
|
|||
func didPressEditName() {
|
||||
Logger.info("\(logTag) \(#function)")
|
||||
|
||||
// TODO:
|
||||
let view = EditContactShareNameViewController(contactShare: contactShare, delegate: self)
|
||||
self.navigationController?.pushViewController(view, animated: true)
|
||||
}
|
||||
|
||||
// MARK: - EditContactShareNameViewControllerDelegate
|
||||
|
||||
public func editContactShareNameView(_ editContactShareNameView: EditContactShareNameViewController, didEditContactShare contactShare: OWSContact) {
|
||||
self.contactShare = contactShare
|
||||
|
||||
nameLabel.text = contactShare.displayName
|
||||
|
||||
self.updateNavigationBar()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,347 @@
|
|||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SignalServiceKit
|
||||
|
||||
@objc
|
||||
public protocol ContactNameFieldViewDelegate: class {
|
||||
func nameFieldDidChange()
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
class ContactNameFieldView: UIView {
|
||||
weak var delegate: ContactNameFieldViewDelegate?
|
||||
|
||||
let name: String
|
||||
let initialValue: String?
|
||||
|
||||
var valueView: UITextField!
|
||||
|
||||
var hasUnsavedChanges = false
|
||||
|
||||
// MARK: - Initializers
|
||||
|
||||
@available(*, unavailable, message: "use other constructor instead.")
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("Unimplemented")
|
||||
}
|
||||
|
||||
required init(name: String, value: String?, delegate: ContactNameFieldViewDelegate) {
|
||||
self.name = name
|
||||
self.initialValue = value
|
||||
self.delegate = delegate
|
||||
|
||||
super.init(frame: CGRect.zero)
|
||||
|
||||
self.isUserInteractionEnabled = true
|
||||
self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(wasTapped)))
|
||||
|
||||
createContents()
|
||||
}
|
||||
|
||||
func createContents() {
|
||||
let vMargin = CGFloat(10)
|
||||
self.layoutMargins = UIEdgeInsets(top: vMargin, left: 0, bottom: vMargin, right: 0)
|
||||
|
||||
let stackView = UIStackView()
|
||||
stackView.axis = .horizontal
|
||||
stackView.alignment = .center
|
||||
stackView.layoutMargins = .zero
|
||||
stackView.spacing = 10
|
||||
self.addSubview(stackView)
|
||||
stackView.autoPinTopToSuperviewMargin()
|
||||
stackView.autoPinBottomToSuperviewMargin()
|
||||
stackView.autoPinLeadingToSuperviewMargin()
|
||||
stackView.autoPinTrailingToSuperviewMargin()
|
||||
|
||||
let nameLabel = UILabel()
|
||||
nameLabel.text = name
|
||||
nameLabel.font = UIFont.ows_dynamicTypeBody
|
||||
nameLabel.textColor = UIColor.ows_materialBlue
|
||||
nameLabel.lineBreakMode = .byTruncatingTail
|
||||
stackView.addArrangedSubview(nameLabel)
|
||||
nameLabel.setContentHuggingHigh()
|
||||
nameLabel.setCompressionResistanceHigh()
|
||||
|
||||
valueView = UITextField()
|
||||
if let initialValue = initialValue {
|
||||
valueView.text = initialValue
|
||||
}
|
||||
valueView.font = UIFont.ows_dynamicTypeBody
|
||||
valueView.textColor = UIColor.black
|
||||
stackView.addArrangedSubview(valueView)
|
||||
|
||||
valueView.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
|
||||
}
|
||||
|
||||
func wasTapped(sender: UIGestureRecognizer) {
|
||||
Logger.info("\(self.logTag) \(#function)")
|
||||
|
||||
guard sender.state == .recognized else {
|
||||
return
|
||||
}
|
||||
|
||||
valueView.becomeFirstResponder()
|
||||
}
|
||||
|
||||
func textFieldDidChange(sender: UITextField) {
|
||||
Logger.info("\(self.logTag) \(#function)")
|
||||
|
||||
hasUnsavedChanges = true
|
||||
|
||||
guard let delegate = self.delegate else {
|
||||
owsFail("\(logTag) missing delegate.")
|
||||
return
|
||||
}
|
||||
|
||||
delegate.nameFieldDidChange()
|
||||
}
|
||||
|
||||
public func value() -> String {
|
||||
guard let value = valueView.text else {
|
||||
return ""
|
||||
}
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
@objc
|
||||
public protocol EditContactShareNameViewControllerDelegate: class {
|
||||
func editContactShareNameView(_ editContactShareNameView: EditContactShareNameViewController, didEditContactShare contactShare: OWSContact)
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
@objc
|
||||
public class EditContactShareNameViewController: OWSViewController, ContactNameFieldViewDelegate {
|
||||
weak var delegate: EditContactShareNameViewControllerDelegate?
|
||||
|
||||
let contactShare: OWSContact
|
||||
|
||||
var namePrefixView: ContactNameFieldView!
|
||||
var givenNameView: ContactNameFieldView!
|
||||
var middleNameView: ContactNameFieldView!
|
||||
var familyNameView: ContactNameFieldView!
|
||||
var nameSuffixView: ContactNameFieldView!
|
||||
|
||||
var fieldViews = [ContactNameFieldView]()
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
@available(*, unavailable, message:"use other constructor instead.")
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
fatalError("unimplemented")
|
||||
}
|
||||
|
||||
@objc
|
||||
required public init(contactShare: OWSContact, delegate: EditContactShareNameViewControllerDelegate) {
|
||||
self.contactShare = contactShare
|
||||
self.delegate = delegate
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
buildFields()
|
||||
}
|
||||
|
||||
func buildFields() {
|
||||
namePrefixView = ContactNameFieldView(name: NSLocalizedString("CONTACT_FIELD_NAME_PREFIX", comment: "Label for the 'name prefix' field of a contact."),
|
||||
value: contactShare.namePrefix, delegate: self)
|
||||
givenNameView = ContactNameFieldView(name: NSLocalizedString("CONTACT_FIELD_GIVEN_NAME", comment: "Label for the 'given name' field of a contact."),
|
||||
value: contactShare.givenName, delegate: self)
|
||||
middleNameView = ContactNameFieldView(name: NSLocalizedString("CONTACT_FIELD_MIDDLE_NAME", comment: "Label for the 'middle name' field of a contact."),
|
||||
value: contactShare.middleName, delegate: self)
|
||||
familyNameView = ContactNameFieldView(name: NSLocalizedString("CONTACT_FIELD_FAMILY_NAME", comment: "Label for the 'family name' field of a contact."),
|
||||
value: contactShare.familyName, delegate: self)
|
||||
nameSuffixView = ContactNameFieldView(name: NSLocalizedString("CONTACT_FIELD_NAME_SUFFIX", comment: "Label for the 'name suffix' field of a contact."),
|
||||
value: contactShare.nameSuffix, delegate: self)
|
||||
fieldViews = [
|
||||
namePrefixView ,
|
||||
givenNameView ,
|
||||
middleNameView ,
|
||||
familyNameView ,
|
||||
nameSuffixView
|
||||
]
|
||||
}
|
||||
|
||||
override public var canBecomeFirstResponder: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
override public func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
updateNavigationBar()
|
||||
}
|
||||
|
||||
override public func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
}
|
||||
|
||||
override public func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
}
|
||||
|
||||
override public func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
}
|
||||
|
||||
override public func loadView() {
|
||||
super.loadView()
|
||||
|
||||
self.navigationItem.title = NSLocalizedString("CONTACT_SHARE_EDIT_NAME_VIEW_TITLE",
|
||||
comment: "Title for the 'edit contact share name' view.")
|
||||
|
||||
self.view.preservesSuperviewLayoutMargins = false
|
||||
self.view.backgroundColor = UIColor.white
|
||||
|
||||
updateContent()
|
||||
|
||||
updateNavigationBar()
|
||||
}
|
||||
|
||||
func hasUnsavedChanges() -> Bool {
|
||||
for fieldView in fieldViews {
|
||||
if fieldView.hasUnsavedChanges {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func updateNavigationBar() {
|
||||
self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel,
|
||||
target: self,
|
||||
action: #selector(didPressCancel))
|
||||
|
||||
if hasUnsavedChanges() {
|
||||
self.navigationItem.rightBarButtonItem =
|
||||
UIBarButtonItem(barButtonSystemItem: .save,
|
||||
target: self,
|
||||
action: #selector(didPressSave))
|
||||
} else {
|
||||
self.navigationItem.rightBarButtonItem = nil
|
||||
}
|
||||
}
|
||||
|
||||
private func updateContent() {
|
||||
SwiftAssertIsOnMainThread(#function)
|
||||
|
||||
guard let rootView = self.view else {
|
||||
owsFail("\(logTag) missing root view.")
|
||||
return
|
||||
}
|
||||
|
||||
for subview in rootView.subviews {
|
||||
subview.removeFromSuperview()
|
||||
}
|
||||
|
||||
let scrollView = UIScrollView()
|
||||
scrollView.preservesSuperviewLayoutMargins = false
|
||||
self.view.addSubview(scrollView)
|
||||
scrollView.layoutMargins = .zero
|
||||
scrollView.autoPinWidthToSuperview()
|
||||
scrollView.autoPin(toTopLayoutGuideOf: self, withInset: 0)
|
||||
scrollView.autoPinEdge(toSuperviewEdge: .bottom)
|
||||
|
||||
let fieldsView = createFieldsView()
|
||||
|
||||
// See notes on how to use UIScrollView with iOS Auto Layout:
|
||||
//
|
||||
// https://developer.apple.com/library/content/releasenotes/General/RN-iOSSDK-6_0/
|
||||
scrollView.addSubview(fieldsView)
|
||||
fieldsView.autoPinLeadingToSuperviewMargin()
|
||||
fieldsView.autoPinTrailingToSuperviewMargin()
|
||||
fieldsView.autoPinEdge(toSuperviewEdge: .top)
|
||||
fieldsView.autoPinEdge(toSuperviewEdge: .bottom)
|
||||
}
|
||||
|
||||
private func createFieldsView() -> UIView {
|
||||
SwiftAssertIsOnMainThread(#function)
|
||||
|
||||
let fieldsView = UIView.container()
|
||||
fieldsView.layoutMargins = .zero
|
||||
fieldsView.preservesSuperviewLayoutMargins = false
|
||||
|
||||
var lastRow: UIView?
|
||||
|
||||
let addSpacerRow = {
|
||||
guard let prevRow = lastRow else {
|
||||
owsFail("\(self.logTag) missing last row")
|
||||
return
|
||||
}
|
||||
let row = UIView()
|
||||
row.backgroundColor = UIColor(rgbHex: 0xdedee1)
|
||||
fieldsView.addSubview(row)
|
||||
row.autoSetDimension(.height, toSize: 1)
|
||||
row.autoPinLeadingToSuperviewMargin(withInset: self.hMargin)
|
||||
row.autoPinTrailingToSuperviewMargin()
|
||||
row.autoPinEdge(.top, to: .bottom, of: prevRow, withOffset: 0)
|
||||
lastRow = row
|
||||
}
|
||||
|
||||
let addRow: ((UIView) -> Void) = { (row) in
|
||||
if lastRow != nil {
|
||||
addSpacerRow()
|
||||
}
|
||||
fieldsView.addSubview(row)
|
||||
row.autoPinLeadingToSuperviewMargin(withInset: self.hMargin)
|
||||
row.autoPinTrailingToSuperviewMargin(withInset: self.hMargin)
|
||||
if let lastRow = lastRow {
|
||||
row.autoPinEdge(.top, to: .bottom, of: lastRow, withOffset: 0)
|
||||
} else {
|
||||
row.autoPinEdge(toSuperviewEdge: .top, withInset: 0)
|
||||
}
|
||||
lastRow = row
|
||||
}
|
||||
|
||||
for fieldView in fieldViews {
|
||||
addRow(fieldView)
|
||||
}
|
||||
|
||||
lastRow?.autoPinEdge(toSuperviewEdge: .bottom, withInset: 0)
|
||||
|
||||
return fieldsView
|
||||
}
|
||||
|
||||
private let hMargin = CGFloat(16)
|
||||
|
||||
// MARK: -
|
||||
|
||||
func didPressSave() {
|
||||
Logger.info("\(logTag) \(#function)")
|
||||
|
||||
let modifiedContactShare = contactShare.copy(withNamePrefix: namePrefixView.value(),
|
||||
givenName: givenNameView.value(),
|
||||
middleName: middleNameView.value(),
|
||||
familyName: familyNameView.value(),
|
||||
nameSuffix: nameSuffixView.value())
|
||||
|
||||
guard let delegate = self.delegate else {
|
||||
owsFail("\(logTag) missing delegate.")
|
||||
return
|
||||
}
|
||||
|
||||
delegate.editContactShareNameView(self, didEditContactShare: modifiedContactShare)
|
||||
|
||||
self.navigationController?.popViewController(animated: true)
|
||||
}
|
||||
|
||||
func didPressCancel() {
|
||||
Logger.info("\(logTag) \(#function)")
|
||||
|
||||
self.navigationController?.popViewController(animated: true)
|
||||
}
|
||||
|
||||
// MARK: - ContactNameFieldViewDelegate
|
||||
|
||||
public func nameFieldDidChange() {
|
||||
updateNavigationBar()
|
||||
}
|
||||
}
|
|
@ -128,6 +128,20 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value);
|
|||
|
||||
- (NSString *)debugDescription;
|
||||
|
||||
#pragma mark - Creation and Derivation
|
||||
|
||||
- (OWSContact *)newContactWithNamePrefix:(nullable NSString *)namePrefix
|
||||
givenName:(nullable NSString *)givenName
|
||||
middleName:(nullable NSString *)middleName
|
||||
familyName:(nullable NSString *)familyName
|
||||
nameSuffix:(nullable NSString *)nameSuffix;
|
||||
|
||||
- (OWSContact *)copyContactWithNamePrefix:(nullable NSString *)namePrefix
|
||||
givenName:(nullable NSString *)givenName
|
||||
middleName:(nullable NSString *)middleName
|
||||
familyName:(nullable NSString *)familyName
|
||||
nameSuffix:(nullable NSString *)nameSuffix;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
@ -154,10 +168,6 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value);
|
|||
+ (nullable OWSSignalServiceProtosDataMessageContact *)protoForContact:(OWSContact *)contact;
|
||||
+ (OWSContact *_Nullable)contactForDataMessage:(OWSSignalServiceProtosDataMessage *)dataMessage;
|
||||
|
||||
//#pragma mark - Old Contacts
|
||||
//
|
||||
//+ (nullable OWSContact *)contactForOldContact:(Contact *)oldContact
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -124,7 +124,7 @@ NSString *NSStringForContactEmailType(OWSContactEmailType value)
|
|||
DDLogWarn(@"%@ invalid email: %@.", self.logTag, self.email);
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSString *)localizedLabel
|
||||
|
@ -203,7 +203,7 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value)
|
|||
DDLogWarn(@"%@ invalid address; empty.", self.logTag);
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSString *)localizedLabel
|
||||
|
@ -362,6 +362,13 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value)
|
|||
}
|
||||
}
|
||||
|
||||
- (void)updateDisplayName
|
||||
{
|
||||
_displayName = nil;
|
||||
|
||||
[self ensureDisplayName];
|
||||
}
|
||||
|
||||
- (NSString *)debugDescription
|
||||
{
|
||||
NSMutableString *result = [NSMutableString new];
|
||||
|
@ -400,6 +407,55 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value)
|
|||
return result;
|
||||
}
|
||||
|
||||
- (OWSContact *)newContactWithNamePrefix:(nullable NSString *)namePrefix
|
||||
givenName:(nullable NSString *)givenName
|
||||
middleName:(nullable NSString *)middleName
|
||||
familyName:(nullable NSString *)familyName
|
||||
nameSuffix:(nullable NSString *)nameSuffix
|
||||
{
|
||||
OWSContact *newContact = [OWSContact new];
|
||||
|
||||
[newContact setNamePrefix:namePrefix
|
||||
givenName:givenName
|
||||
middleName:middleName
|
||||
familyName:familyName
|
||||
nameSuffix:nameSuffix];
|
||||
|
||||
return newContact;
|
||||
}
|
||||
|
||||
- (OWSContact *)copyContactWithNamePrefix:(nullable NSString *)namePrefix
|
||||
givenName:(nullable NSString *)givenName
|
||||
middleName:(nullable NSString *)middleName
|
||||
familyName:(nullable NSString *)familyName
|
||||
nameSuffix:(nullable NSString *)nameSuffix
|
||||
{
|
||||
OWSContact *contactCopy = [self copy];
|
||||
|
||||
[contactCopy setNamePrefix:namePrefix
|
||||
givenName:givenName
|
||||
middleName:middleName
|
||||
familyName:familyName
|
||||
nameSuffix:nameSuffix];
|
||||
|
||||
return contactCopy;
|
||||
}
|
||||
|
||||
- (void)setNamePrefix:(nullable NSString *)namePrefix
|
||||
givenName:(nullable NSString *)givenName
|
||||
middleName:(nullable NSString *)middleName
|
||||
familyName:(nullable NSString *)familyName
|
||||
nameSuffix:(nullable NSString *)nameSuffix
|
||||
{
|
||||
self.namePrefix = namePrefix.ows_stripped;
|
||||
self.givenName = givenName.ows_stripped;
|
||||
self.middleName = middleName.ows_stripped;
|
||||
self.familyName = familyName.ows_stripped;
|
||||
self.nameSuffix = nameSuffix.ows_stripped;
|
||||
|
||||
[self updateDisplayName];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
@ -960,76 +1016,6 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value)
|
|||
return result;
|
||||
}
|
||||
|
||||
//#pragma mark - Old Contacts
|
||||
//
|
||||
//+ (nullable OWSContact *)contactForOldContact:(Contact *)oldContact
|
||||
//{
|
||||
// OWSAssert(oldContact);
|
||||
// OWSAssert(oldContact.cnContact);
|
||||
//
|
||||
//// DDLogDebug(@"%@ in %s with contact: %@", self.logTag, __PRETTY_FUNCTION__, contact);
|
||||
//
|
||||
// return [self contactForSystemContact:oldContact.cnContact];
|
||||
//
|
||||
//// OWSContact *newContact = [OWSContact new];
|
||||
////
|
||||
//// newContact.givenName = oldContact.firstName;
|
||||
//// newContact.familyName = oldContact.lastName;
|
||||
////
|
||||
//// NSMutableArray<
|
||||
//// OWSContactPhoneNumber *> *newPhoneNumbers = [NSMutableArray new];
|
||||
//// for (NSString *oldPhoneNumber in oldContact.userTextPhoneNumbers) {
|
||||
//// OWSContactPhoneNumber *newPhoneNumber = [OWSContactPhoneNumber new];
|
||||
//// newPhoneNumber.phoneNumber = oldPhoneNumber;
|
||||
//// newPhoneNumber.phoneType = OWSContactPhoneType_Custom;
|
||||
//// [newPhoneNumbers addObject:newPhoneNumber];
|
||||
//// }
|
||||
//// newContact.phoneNumbers = newPhoneNumbers;
|
||||
////
|
||||
//// NSMutableArray<
|
||||
//// OWSContactEmail *> *newEmails = [NSMutableArray new];
|
||||
//// for (NSString *oldEmail in oldContact.emails) {
|
||||
//// OWSContactEmail *newEmail = [OWSContactEmail new];
|
||||
//// newEmail.email = oldEmail;
|
||||
//// newEmail.emailType = OWSContactEmailType_Custom;
|
||||
//// [newEmails addObject:newEmail];
|
||||
//// }
|
||||
//// newContact.emails = newEmails;
|
||||
////
|
||||
//// @interface Contact : MTLModel
|
||||
////
|
||||
//// @property (nullable, readonly, nonatomic) NSString *firstName;
|
||||
//// @property (nullable, readonly, nonatomic) NSString *lastName;
|
||||
//// @property (readonly, nonatomic) NSString *fullName;
|
||||
//// @property (readonly, nonatomic) NSString *comparableNameFirstLast;
|
||||
//// @property (readonly, nonatomic) NSString *comparableNameLastFirst;
|
||||
//// @property (readonly, nonatomic) NSArray<PhoneNumber *> *parsedPhoneNumbers;
|
||||
//// @property (readonly, nonatomic) NSArray<NSString *> *userTextPhoneNumbers;
|
||||
//// @property (readonly, nonatomic) NSArray<NSString *> *emails;
|
||||
//// @property (readonly, nonatomic) NSString *uniqueId;
|
||||
//// @property (nonatomic, readonly) BOOL isSignalContact;
|
||||
////#if TARGET_OS_IOS
|
||||
//// @property (nullable, readonly, nonatomic) UIImage *image;
|
||||
//// @property (nullable, nonatomic, readonly) CNContact *cnContact;
|
||||
////#endif // TARGET_OS_IOS
|
||||
////
|
||||
//// - (NSArray<SignalRecipient *> *)signalRecipientsWithTransaction:(YapDatabaseReadTransaction *)transaction;
|
||||
//// // TODO: Remove this method.
|
||||
//// - (NSArray<NSString *> *)textSecureIdentifiers;
|
||||
////
|
||||
////#if TARGET_OS_IOS
|
||||
////
|
||||
//// - (instancetype)initWithSystemContact:(CNContact *)contact NS_AVAILABLE_IOS(9_0);
|
||||
////
|
||||
//// - (NSString *)nameForPhoneNumber:(NSString *)recipientId;
|
||||
////
|
||||
////#endif // TARGET_OS_IOS
|
||||
////
|
||||
//// + (NSComparator)comparatorSortingNamesByFirstThenLast:(BOOL)firstNameOrdering;
|
||||
////
|
||||
//// @end
|
||||
//}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
Loading…
Reference in New Issue