mirror of https://github.com/oxen-io/session-ios
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1134 lines
43 KiB
Swift
1134 lines
43 KiB
Swift
7 years ago
|
//
|
||
|
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||
|
//
|
||
|
|
||
|
import Foundation
|
||
|
import SignalServiceKit
|
||
|
//import SignalMessaging
|
||
|
//import AVFoundation
|
||
|
//import MediaPlayer
|
||
|
//import Foundation
|
||
|
//import SignalServiceKit
|
||
|
//import SignalMessaging
|
||
|
//import Reachability
|
||
|
//import ContactsUI
|
||
|
//import MessageUI
|
||
|
|
||
|
@objc
|
||
|
public protocol ApproveContactShareViewControllerDelegate: class {
|
||
|
func approveContactShare(_ approveContactShare: ApproveContactShareViewController, didApproveContactShare contactShare: OWSContact)
|
||
|
}
|
||
|
|
||
|
// MARK: -
|
||
|
|
||
|
//protocol ContactShareField: class {
|
||
|
// func localizedLabel() -> String
|
||
|
// func isIncluded() -> Bool
|
||
|
// func setIsIncluded(isIncluded: Bool)
|
||
|
//}
|
||
|
|
||
|
// MARK: -
|
||
|
|
||
|
class ContactShareField: NSObject {
|
||
|
|
||
|
var isIncludedFlag = true
|
||
|
|
||
|
// override required init() {
|
||
|
// super.init()
|
||
|
// }
|
||
|
|
||
|
func localizedLabel() -> String {
|
||
|
preconditionFailure("This method must be overridden")
|
||
|
}
|
||
|
|
||
|
func isIncluded() -> Bool {
|
||
|
return isIncludedFlag
|
||
|
}
|
||
|
|
||
|
func setIsIncluded(isIncluded: Bool) {
|
||
|
isIncludedFlag = isIncluded
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// MARK: -
|
||
|
|
||
|
class ContactSharePhoneNumber: ContactShareField {
|
||
|
|
||
|
let value: OWSContactPhoneNumber
|
||
|
|
||
|
required init(_ value: OWSContactPhoneNumber) {
|
||
|
self.value = value
|
||
|
|
||
|
super.init()
|
||
|
}
|
||
|
|
||
|
override func localizedLabel() -> String {
|
||
|
return value.localizedLabel()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// MARK: -
|
||
|
|
||
|
class ContactShareEmail: ContactShareField {
|
||
|
|
||
|
let value: OWSContactEmail
|
||
|
|
||
|
required init(_ value: OWSContactEmail) {
|
||
|
self.value = value
|
||
|
|
||
|
super.init()
|
||
|
}
|
||
|
|
||
|
override func localizedLabel() -> String {
|
||
|
return value.localizedLabel()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// MARK: -
|
||
|
|
||
|
class ContactShareAddress: ContactShareField {
|
||
|
|
||
|
let value: OWSContactAddress
|
||
|
|
||
|
required init(_ value: OWSContactAddress) {
|
||
|
self.value = value
|
||
|
|
||
|
super.init()
|
||
|
}
|
||
|
|
||
|
override func localizedLabel() -> String {
|
||
|
return value.localizedLabel()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// MARK: -
|
||
|
|
||
|
class ContactShareFieldView: UIView {
|
||
|
|
||
|
let field: ContactShareField
|
||
|
|
||
|
let previewViewBlock : (() -> UIView)
|
||
|
|
||
|
private var checkbox: UIButton!
|
||
|
|
||
|
// MARK: - Initializers
|
||
|
|
||
|
@available(*, unavailable, message: "use init(call:) constructor instead.")
|
||
|
required init?(coder aDecoder: NSCoder) {
|
||
|
fatalError("Unimplemented")
|
||
|
}
|
||
|
|
||
|
required init(field: ContactShareField, previewViewBlock : @escaping (() -> UIView)) {
|
||
|
self.field = field
|
||
|
self.previewViewBlock = previewViewBlock
|
||
|
|
||
|
super.init(frame: CGRect.zero)
|
||
|
|
||
|
self.isUserInteractionEnabled = true
|
||
|
self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(wasTapped)))
|
||
|
|
||
|
createContents()
|
||
|
}
|
||
|
|
||
|
let hSpacing = CGFloat(10)
|
||
|
let hMargin = CGFloat(0)
|
||
|
|
||
|
func createContents() {
|
||
|
// self.addRedBorder()
|
||
|
|
||
|
self.layoutMargins.left = 0
|
||
|
self.layoutMargins.right = 0
|
||
|
|
||
|
let checkbox = UIButton(type: .custom)
|
||
|
self.checkbox = checkbox
|
||
|
// TODO: Use real assets.
|
||
|
checkbox.setTitle("☐", for: .normal)
|
||
|
checkbox.setTitle("☒", for: .selected)
|
||
|
checkbox.setTitleColor(UIColor.black, for: .normal)
|
||
|
checkbox.setTitleColor(UIColor.black, for: .selected)
|
||
|
checkbox.titleLabel?.font = UIFont.ows_dynamicTypeBody
|
||
|
checkbox.isSelected = field.isIncluded()
|
||
|
// Disable the checkbox; the entire row is hot.
|
||
|
checkbox.isUserInteractionEnabled = false
|
||
|
// checkbox.addTarget(self, action: #selector(checkboxTapped), for: .touchUpInside)
|
||
|
addSubview(checkbox)
|
||
|
checkbox.autoPinEdge(toSuperviewEdge: .leading, withInset: hMargin)
|
||
|
checkbox.autoVCenterInSuperview()
|
||
|
checkbox.setCompressionResistanceHigh()
|
||
|
checkbox.setContentHuggingHigh()
|
||
|
// checkbox.addRedBorder()
|
||
|
|
||
|
let nameLabel = UILabel()
|
||
|
nameLabel.text = field.localizedLabel()
|
||
|
nameLabel.font = UIFont.ows_dynamicTypeCaption1
|
||
|
nameLabel.textColor = UIColor.black
|
||
|
nameLabel.lineBreakMode = .byTruncatingTail
|
||
|
addSubview(nameLabel)
|
||
|
nameLabel.autoPinTopToSuperviewMargin()
|
||
|
nameLabel.autoPinLeading(toTrailingEdgeOf: checkbox, offset: hSpacing)
|
||
|
nameLabel.autoPinTrailingToSuperviewMargin(withInset: hMargin)
|
||
|
|
||
|
let previewView = previewViewBlock()
|
||
|
addSubview(previewView)
|
||
|
previewView.autoPinEdge(.top, to: .bottom, of: nameLabel, withOffset: 3)
|
||
|
previewView.autoPinBottomToSuperviewMargin()
|
||
|
previewView.autoPinLeading(toTrailingEdgeOf: checkbox, offset: hSpacing)
|
||
|
previewView.autoPinTrailingToSuperviewMargin(withInset: hMargin)
|
||
|
}
|
||
|
|
||
|
// func checkboxTapped(sender: UIButton) {
|
||
|
// field.setIsIncluded(isIncluded: checkbox.isSelected)
|
||
|
// }
|
||
|
|
||
|
func wasTapped(sender: UIGestureRecognizer) {
|
||
|
Logger.info("\(self.logTag) \(#function)")
|
||
|
|
||
|
guard sender.state == .recognized else {
|
||
|
return
|
||
|
}
|
||
|
checkbox.isSelected = !checkbox.isSelected
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// MARK: -
|
||
|
|
||
|
@objc
|
||
|
public class ApproveContactShareViewController: OWSViewController
|
||
|
//, CaptioningToolbarDelegate, PlayerProgressBarDelegate, OWSVideoPlayerDelegate
|
||
|
{
|
||
|
weak var delegate: ApproveContactShareViewControllerDelegate?
|
||
|
|
||
|
let contactsManager: OWSContactsManager
|
||
|
|
||
|
let contactShare: OWSContact
|
||
|
|
||
|
// // We sometimes shrink the attachment view so that it remains somewhat visible
|
||
|
// // when the keyboard is presented.
|
||
|
// enum AttachmentViewScale {
|
||
|
// case fullsize, compact
|
||
|
// }
|
||
|
//
|
||
|
// // MARK: Properties
|
||
|
//
|
||
|
// let attachment: SignalAttachment
|
||
|
// private var videoPlayer: OWSVideoPlayer?
|
||
|
//
|
||
|
// private(set) var bottomToolbar: UIView!
|
||
|
// private(set) var mediaMessageView: MediaMessageView!
|
||
|
// private(set) var scrollView: UIScrollView!
|
||
|
// private(set) var contentContainer: UIView!
|
||
|
// private(set) var playVideoButton: UIView?
|
||
|
|
||
|
var fields = [ContactShareField]()
|
||
|
var fieldViews = [ContactShareFieldView]()
|
||
|
|
||
|
// MARK: Initializers
|
||
|
|
||
|
@available(*, unavailable, message:"use other constructor instead.")
|
||
|
required public init?(coder aDecoder: NSCoder) {
|
||
|
fatalError("unimplemented")
|
||
|
}
|
||
|
|
||
|
@objc
|
||
|
required public init(contactShare: OWSContact, contactsManager: OWSContactsManager, delegate: ApproveContactShareViewControllerDelegate) {
|
||
|
self.contactsManager = contactsManager
|
||
|
self.contactShare = contactShare
|
||
|
self.delegate = delegate
|
||
|
|
||
|
super.init(nibName: nil, bundle: nil)
|
||
|
|
||
|
buildFields()
|
||
|
}
|
||
|
|
||
|
func buildFields() {
|
||
|
var fields = [ContactShareField]()
|
||
|
var fieldViews = [ContactShareFieldView]()
|
||
|
|
||
|
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)
|
||
|
})
|
||
|
fieldViews.append(fieldView)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
})
|
||
|
fieldViews.append(fieldView)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
})
|
||
|
fieldViews.append(fieldView)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
self.fields = fields
|
||
|
self.fieldViews = fieldViews
|
||
|
}
|
||
|
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
////
|
||
|
//// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||
|
////
|
||
|
//
|
||
|
//
|
||
|
//class TappableView: UIView {
|
||
|
// let actionBlock : (() -> Void)
|
||
|
//
|
||
|
// // MARK: - Initializers
|
||
|
//
|
||
|
// @available(*, unavailable, message: "use init(call:) constructor instead.")
|
||
|
// required init?(coder aDecoder: NSCoder) {
|
||
|
// fatalError("Unimplemented")
|
||
|
// }
|
||
|
//
|
||
|
// required init(actionBlock : @escaping () -> Void) {
|
||
|
// self.actionBlock = actionBlock
|
||
|
// super.init(frame: CGRect.zero)
|
||
|
//
|
||
|
// self.isUserInteractionEnabled = true
|
||
|
// self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(wasTapped)))
|
||
|
// }
|
||
|
//
|
||
|
// func wasTapped(sender: UIGestureRecognizer) {
|
||
|
// Logger.info("\(self.logTag) \(#function)")
|
||
|
//
|
||
|
// guard sender.state == .recognized else {
|
||
|
// return
|
||
|
// }
|
||
|
// actionBlock()
|
||
|
// }
|
||
|
//}
|
||
|
//
|
||
|
//// MARK: -
|
||
|
//
|
||
|
//class ContactViewController: OWSViewController, CNContactViewControllerDelegate {
|
||
|
//
|
||
|
// let TAG = "[ContactView]"
|
||
|
|
||
|
// enum ContactViewMode {
|
||
|
// case systemContactWithSignal,
|
||
|
// systemContactWithoutSignal,
|
||
|
// nonSystemContact,
|
||
|
// noPhoneNumber,
|
||
|
// unknown
|
||
|
// }
|
||
|
//
|
||
|
// private var hasLoadedView = false
|
||
|
//
|
||
|
// private var viewMode = ContactViewMode.unknown {
|
||
|
// didSet {
|
||
|
// SwiftAssertIsOnMainThread(#function)
|
||
|
//
|
||
|
// if oldValue != viewMode && hasLoadedView {
|
||
|
// updateContent()
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
//
|
||
|
// var reachability: Reachability?
|
||
|
|
||
|
override public var canBecomeFirstResponder: Bool {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
// private let contact: OWSContact
|
||
|
//
|
||
|
// // MARK: - Initializers
|
||
|
//
|
||
|
// @available(*, unavailable, message: "use init(call:) constructor instead.")
|
||
|
// required init?(coder aDecoder: NSCoder) {
|
||
|
// fatalError("Unimplemented")
|
||
|
// }
|
||
|
//
|
||
|
// required init(contact: OWSContact) {
|
||
|
// contactsManager = Environment.current().contactsManager
|
||
|
// self.contact = contact
|
||
|
//
|
||
|
// super.init(nibName: nil, bundle: nil)
|
||
|
//
|
||
|
// tryToDetermineMode()
|
||
|
//
|
||
|
// NotificationCenter.default.addObserver(forName: .OWSContactsManagerSignalAccountsDidChange, object: nil, queue: nil) { [weak self] _ in
|
||
|
// guard let strongSelf = self else { return }
|
||
|
// strongSelf.tryToDetermineMode()
|
||
|
// }
|
||
|
//
|
||
|
// reachability = Reachability.forInternetConnection()
|
||
|
//
|
||
|
// NotificationCenter.default.addObserver(forName: .reachabilityChanged, object: nil, queue: nil) { [weak self] _ in
|
||
|
// guard let strongSelf = self else { return }
|
||
|
// strongSelf.tryToDetermineMode()
|
||
|
// }
|
||
|
// }
|
||
|
|
||
|
// MARK: - View Lifecycle
|
||
|
|
||
|
override public func viewWillAppear(_ animated: Bool) {
|
||
|
super.viewWillAppear(animated)
|
||
|
|
||
|
updateNavigationBar()
|
||
|
|
||
|
// UIUtil.applySignalAppearence()
|
||
|
//
|
||
|
// if let navigationController = self.navigationController {
|
||
|
// navigationController.isNavigationBarHidden = true
|
||
|
// }
|
||
|
//
|
||
|
// self.becomeFirstResponder()
|
||
|
//
|
||
|
// contactsManager.requestSystemContactsOnce(completion: { [weak self] _ in
|
||
|
// guard let strongSelf = self else { return }
|
||
|
// strongSelf.tryToDetermineMode()
|
||
|
// })
|
||
|
}
|
||
|
|
||
|
override public func viewDidAppear(_ animated: Bool) {
|
||
|
super.viewDidAppear(animated)
|
||
|
//
|
||
|
// UIUtil.applySignalAppearence()
|
||
|
//
|
||
|
// self.becomeFirstResponder()
|
||
|
}
|
||
|
|
||
|
override public func viewWillDisappear(_ animated: Bool) {
|
||
|
super.viewWillDisappear(animated)
|
||
|
|
||
|
// if let navigationController = self.navigationController {
|
||
|
// navigationController.isNavigationBarHidden = false
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
override public func viewDidDisappear(_ animated: Bool) {
|
||
|
super.viewDidDisappear(animated)
|
||
|
}
|
||
|
|
||
|
override public func loadView() {
|
||
|
super.loadView()
|
||
|
|
||
|
self.navigationItem.title = NSLocalizedString("CONTACT_SHARE_APPROVAL_VIEW_TITLE",
|
||
|
comment: "Title for the 'Approve contact share' view.")
|
||
|
|
||
|
self.view.preservesSuperviewLayoutMargins = false
|
||
|
self.view.backgroundColor = UIColor.white
|
||
|
// self.view.backgroundColor = UIColor(rgbHex: 0xefeff4)
|
||
|
|
||
|
updateContent()
|
||
|
|
||
|
// hasLoadedView = true
|
||
|
|
||
|
updateNavigationBar()
|
||
|
}
|
||
|
|
||
|
// TODO: Show error.
|
||
|
func canShareContact() -> Bool {
|
||
|
return contactShare.ows_isValid()
|
||
|
}
|
||
|
|
||
|
func updateNavigationBar() {
|
||
|
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))
|
||
|
} else {
|
||
|
self.navigationItem.rightBarButtonItem = nil
|
||
|
}
|
||
|
// self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel,
|
||
|
// target: self,
|
||
|
// action: #selector(donePressed))
|
||
|
}
|
||
|
|
||
|
// private func tryToDetermineMode() {
|
||
|
// SwiftAssertIsOnMainThread(#function)
|
||
|
//
|
||
|
// guard phoneNumbersForContact().count > 0 else {
|
||
|
// viewMode = .noPhoneNumber
|
||
|
// return
|
||
|
// }
|
||
|
// if systemContactsWithSignalAccountsForContact().count > 0 {
|
||
|
// viewMode = .systemContactWithSignal
|
||
|
// return
|
||
|
// }
|
||
|
// if systemContactsForContact().count > 0 {
|
||
|
// viewMode = .systemContactWithoutSignal
|
||
|
// return
|
||
|
// }
|
||
|
//
|
||
|
// viewMode = .nonSystemContact
|
||
|
// }
|
||
|
|
||
|
// private func systemContactsWithSignalAccountsForContact() -> [String] {
|
||
|
// SwiftAssertIsOnMainThread(#function)
|
||
|
//
|
||
|
// return phoneNumbersForContact().filter({ (phoneNumber) -> Bool in
|
||
|
// return contactsManager.hasSignalAccount(forRecipientId: phoneNumber)
|
||
|
// })
|
||
|
// }
|
||
|
//
|
||
|
// private func systemContactsForContact() -> [String] {
|
||
|
// SwiftAssertIsOnMainThread(#function)
|
||
|
//
|
||
|
// return phoneNumbersForContact().filter({ (phoneNumber) -> Bool in
|
||
|
// return contactsManager.allContactsMap[phoneNumber] != nil
|
||
|
// })
|
||
|
// }
|
||
|
//
|
||
|
// private func phoneNumbersForContact() -> [String] {
|
||
|
// SwiftAssertIsOnMainThread(#function)
|
||
|
//
|
||
|
// var result = [String]()
|
||
|
// if let phoneNumbers = contact.phoneNumbers {
|
||
|
// for phoneNumber in phoneNumbers {
|
||
|
// result.append(phoneNumber.phoneNumber)
|
||
|
// }
|
||
|
// }
|
||
|
// return result
|
||
|
// }
|
||
|
|
||
|
// private func tryToDetermineModeRetry() {
|
||
|
// // Try again after a minute.
|
||
|
// DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 60.0) { [weak self] in
|
||
|
// guard let strongSelf = self else { return }
|
||
|
// strongSelf.tryToDetermineMode()
|
||
|
// }
|
||
|
// }
|
||
|
|
||
|
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 topView = createTopView()
|
||
|
// rootView.addSubview(topView)
|
||
|
// topView.autoPin(toTopLayoutGuideOf: self, withInset: 0)
|
||
|
// topView.autoPinWidthToSuperview()
|
||
|
|
||
|
// // This view provides a background "below the fold".
|
||
|
// let bottomView = UIView.container()
|
||
|
// bottomView.backgroundColor = UIColor.white
|
||
|
// self.view.addSubview(bottomView)
|
||
|
// bottomView.layoutMargins = .zero
|
||
|
// bottomView.autoPinWidthToSuperview()
|
||
|
// bottomView.autoPinEdge(.top, to: .bottom, of: topView, withOffset: 0)
|
||
|
// bottomView.autoPinEdge(toSuperviewEdge: .bottom)
|
||
|
|
||
|
let scrollView = UIScrollView()
|
||
|
scrollView.preservesSuperviewLayoutMargins = false
|
||
|
self.view.addSubview(scrollView)
|
||
|
scrollView.layoutMargins = .zero
|
||
|
scrollView.autoPinWidthToSuperview()
|
||
|
scrollView.autoPin(toTopLayoutGuideOf: self, withInset: 0)
|
||
|
// scrollView.autoPinEdge(.top, to: .bottom, of: topView, withOffset: 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 createTopView() -> UIView {
|
||
|
// SwiftAssertIsOnMainThread(#function)
|
||
|
//
|
||
|
// let topView = UIView.container()
|
||
|
// topView.backgroundColor = UIColor(rgbHex: 0xefeff4)
|
||
|
// topView.preservesSuperviewLayoutMargins = false
|
||
|
//
|
||
|
// // Back Button
|
||
|
// let backButtonSize = CGFloat(50)
|
||
|
// let backButton = TappableView(actionBlock: { [weak self] _ in
|
||
|
// guard let strongSelf = self else { return }
|
||
|
// strongSelf.didPressDismiss()
|
||
|
// })
|
||
|
// backButton.autoSetDimension(.width, toSize: backButtonSize)
|
||
|
// backButton.autoSetDimension(.height, toSize: backButtonSize)
|
||
|
// topView.addSubview(backButton)
|
||
|
// backButton.autoPin(toTopLayoutGuideOf: self, withInset: 0)
|
||
|
// backButton.autoPinEdge(toSuperviewEdge: .left)
|
||
|
//
|
||
|
// let backIconName = (self.view.isRTL() ? "system_disclosure_indicator" : "system_disclosure_indicator_rtl")
|
||
|
// let backIconImage = UIImage(named: backIconName)?.withRenderingMode(.alwaysTemplate)
|
||
|
// let backIconView = UIImageView(image: backIconImage)
|
||
|
// backIconView.contentMode = .scaleAspectFit
|
||
|
// backIconView.tintColor = UIColor.black.withAlphaComponent(0.6)
|
||
|
// backButton.addSubview(backIconView)
|
||
|
// backIconView.autoCenterInSuperview()
|
||
|
//
|
||
|
// // TODO: Use actual avatar.
|
||
|
// let avatarSize = CGFloat(100)
|
||
|
//
|
||
|
// let avatarView = AvatarImageView()
|
||
|
// // TODO: What's the best colorSeed value to use?
|
||
|
// let avatarBuilder = OWSContactAvatarBuilder(nonSignalName: contact.displayName,
|
||
|
// colorSeed: contact.displayName,
|
||
|
// diameter: UInt(avatarSize),
|
||
|
// contactsManager: contactsManager)
|
||
|
// avatarView.image = avatarBuilder.build()
|
||
|
// topView.addSubview(avatarView)
|
||
|
// avatarView.autoPin(toTopLayoutGuideOf: self, withInset: 20)
|
||
|
// avatarView.autoHCenterInSuperview()
|
||
|
// avatarView.autoSetDimension(.width, toSize: avatarSize)
|
||
|
// avatarView.autoSetDimension(.height, toSize: avatarSize)
|
||
|
//
|
||
|
// let nameLabel = UILabel()
|
||
|
// nameLabel.text = contact.displayName
|
||
|
// nameLabel.font = UIFont.ows_dynamicTypeTitle2.ows_bold()
|
||
|
// nameLabel.textColor = UIColor.black
|
||
|
// nameLabel.lineBreakMode = .byTruncatingTail
|
||
|
// nameLabel.textAlignment = .center
|
||
|
// topView.addSubview(nameLabel)
|
||
|
// nameLabel.autoPinEdge(.top, to: .bottom, of: avatarView, withOffset: 10)
|
||
|
// nameLabel.autoPinLeadingToSuperviewMargin(withInset: hMargin)
|
||
|
// nameLabel.autoPinTrailingToSuperviewMargin(withInset: hMargin)
|
||
|
//
|
||
|
// var lastView: UIView = nameLabel
|
||
|
//
|
||
|
// if let firstPhoneNumber = contact.phoneNumbers?.first {
|
||
|
// let phoneNumberLabel = UILabel()
|
||
|
// phoneNumberLabel.text = PhoneNumber.bestEffortFormatE164(asLocalizedPhoneNumber: firstPhoneNumber.phoneNumber)
|
||
|
// phoneNumberLabel.font = UIFont.ows_dynamicTypeCaption2
|
||
|
// phoneNumberLabel.textColor = UIColor.black
|
||
|
// phoneNumberLabel.lineBreakMode = .byTruncatingTail
|
||
|
// phoneNumberLabel.textAlignment = .center
|
||
|
// topView.addSubview(phoneNumberLabel)
|
||
|
// phoneNumberLabel.autoPinEdge(.top, to: .bottom, of: lastView, withOffset: 5)
|
||
|
// phoneNumberLabel.autoPinLeadingToSuperviewMargin(withInset: hMargin)
|
||
|
// phoneNumberLabel.autoPinTrailingToSuperviewMargin(withInset: hMargin)
|
||
|
// lastView = phoneNumberLabel
|
||
|
// }
|
||
|
//
|
||
|
// switch viewMode {
|
||
|
// case .systemContactWithSignal:
|
||
|
// // Show actions buttons for system contacts with a Signal account.
|
||
|
// let stackView = UIStackView()
|
||
|
// stackView.axis = .horizontal
|
||
|
// stackView.distribution = .fillEqually
|
||
|
// stackView.addArrangedSubview(createCircleActionButton(text: NSLocalizedString("ACTION_SEND_MESSAGE",
|
||
|
// comment: "Label for 'sent message' button in contact view."),
|
||
|
// actionBlock: { [weak self] _ in
|
||
|
// guard let strongSelf = self else { return }
|
||
|
// strongSelf.didPressSendMessage()
|
||
|
// }))
|
||
|
// stackView.addArrangedSubview(createCircleActionButton(text: NSLocalizedString("ACTION_AUDIO_CALL",
|
||
|
// comment: "Label for 'audio call' button in contact view."),
|
||
|
// actionBlock: { [weak self] _ in
|
||
|
// guard let strongSelf = self else { return }
|
||
|
// strongSelf.didPressAudioCall()
|
||
|
// }))
|
||
|
// stackView.addArrangedSubview(createCircleActionButton(text: NSLocalizedString("ACTION_VIDEO_CALL",
|
||
|
// comment: "Label for 'video call' button in contact view."),
|
||
|
// actionBlock: { [weak self] _ in
|
||
|
// guard let strongSelf = self else { return }
|
||
|
// strongSelf.didPressVideoCall()
|
||
|
// }))
|
||
|
// topView.addSubview(stackView)
|
||
|
// stackView.autoPinEdge(.top, to: .bottom, of: lastView, withOffset: 20)
|
||
|
// stackView.autoPinLeadingToSuperviewMargin(withInset: hMargin)
|
||
|
// stackView.autoPinTrailingToSuperviewMargin(withInset: hMargin)
|
||
|
// lastView = stackView
|
||
|
// case .systemContactWithoutSignal:
|
||
|
// // Show invite button for system contacts without a Signal account.
|
||
|
// let inviteButton = createLargePillButton(text: NSLocalizedString("ACTION_INVITE",
|
||
|
// comment: "Label for 'invite' button in contact view."),
|
||
|
// actionBlock: { [weak self] _ in
|
||
|
// guard let strongSelf = self else { return }
|
||
|
// strongSelf.didPressInvite()
|
||
|
// })
|
||
|
// topView.addSubview(inviteButton)
|
||
|
// inviteButton.autoPinEdge(.top, to: .bottom, of: lastView, withOffset: 20)
|
||
|
// inviteButton.autoPinLeadingToSuperviewMargin(withInset: 55)
|
||
|
// inviteButton.autoPinTrailingToSuperviewMargin(withInset: 55)
|
||
|
// lastView = inviteButton
|
||
|
// case .nonSystemContact:
|
||
|
// // Show no action buttons for contacts not in user's device contacts.
|
||
|
// break
|
||
|
// case .noPhoneNumber:
|
||
|
// // Show no action buttons for contacts without a phone number.
|
||
|
// break
|
||
|
// case .unknown:
|
||
|
// let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
|
||
|
// topView.addSubview(activityIndicator)
|
||
|
// activityIndicator.autoPinEdge(.top, to: .bottom, of: lastView, withOffset: 10)
|
||
|
// activityIndicator.autoHCenterInSuperview()
|
||
|
// lastView = activityIndicator
|
||
|
// break
|
||
|
// }
|
||
|
//
|
||
|
// lastView.autoPinEdge(toSuperviewEdge: .bottom, withInset: 15)
|
||
|
//
|
||
|
// return topView
|
||
|
// }
|
||
|
|
||
|
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)
|
||
|
}
|
||
|
|
||
|
// if viewMode == .nonSystemContact {
|
||
|
// addRow(createActionRow(labelText: NSLocalizedString("CONVERSATION_SETTINGS_NEW_CONTACT",
|
||
|
// comment: "Label for 'new contact' button in conversation settings view."),
|
||
|
// action: #selector(didPressCreateNewContact)))
|
||
|
//
|
||
|
// addRow(createActionRow(labelText: NSLocalizedString("CONVERSATION_SETTINGS_ADD_TO_EXISTING_CONTACT",
|
||
|
// comment: "Label for 'new contact' button in conversation settings view."),
|
||
|
// action: #selector(didPressAddToExistingContact)))
|
||
|
// }
|
||
|
//
|
||
|
// // TODO: Not designed yet.
|
||
|
// // if viewMode == .systemContactWithSignal ||
|
||
|
// // viewMode == .systemContactWithoutSignal {
|
||
|
// // addRow(createActionRow(labelText:NSLocalizedString("ACTION_SHARE_CONTACT",
|
||
|
// // comment:"Label for 'share contact' button."),
|
||
|
// // action:#selector(didPressShareContact)))
|
||
|
// // }
|
||
|
//
|
||
|
// if let phoneNumbers = contact.phoneNumbers {
|
||
|
// for phoneNumber in phoneNumbers {
|
||
|
// // TODO: Try to format the phone number nicely.
|
||
|
// addRow(createNameValueRow(name: phoneNumber.localizedLabel(),
|
||
|
// value:
|
||
|
// PhoneNumber.bestEffortFormatE164(asLocalizedPhoneNumber: phoneNumber.phoneNumber),
|
||
|
// actionBlock: {
|
||
|
// guard let url = NSURL(string: "tel:\(phoneNumber.phoneNumber)") else {
|
||
|
// owsFail("\(ContactViewController.logTag) could not open phone number.")
|
||
|
// return
|
||
|
// }
|
||
|
// UIApplication.shared.openURL(url as URL)
|
||
|
// }))
|
||
|
// }
|
||
|
// }
|
||
|
//
|
||
|
// if let emails = contact.emails {
|
||
|
// for email in emails {
|
||
|
// addRow(createNameValueRow(name: email.localizedLabel(),
|
||
|
// value: email.email,
|
||
|
// actionBlock: {
|
||
|
// guard let url = NSURL(string: "mailto:\(email.email)") else {
|
||
|
// owsFail("\(ContactViewController.logTag) could not open email.")
|
||
|
// return
|
||
|
// }
|
||
|
// UIApplication.shared.openURL(url as URL)
|
||
|
// }))
|
||
|
// }
|
||
|
// }
|
||
|
|
||
|
// TODO: Should we present addresses here too? How?
|
||
|
|
||
|
lastRow?.autoPinEdge(toSuperviewEdge: .bottom, withInset: 0)
|
||
|
|
||
|
return fieldsView
|
||
|
}
|
||
|
|
||
|
private let hMargin = CGFloat(16)
|
||
|
|
||
|
// private func createActionRow(labelText: String, action: Selector) -> UIView {
|
||
|
// let row = UIView()
|
||
|
// row.layoutMargins.left = 0
|
||
|
// row.layoutMargins.right = 0
|
||
|
// row.isUserInteractionEnabled = true
|
||
|
// row.addGestureRecognizer(UITapGestureRecognizer(target: self, action: action))
|
||
|
//
|
||
|
// let label = UILabel()
|
||
|
// label.text = labelText
|
||
|
// label.font = UIFont.ows_dynamicTypeBody
|
||
|
// label.textColor = UIColor.ows_materialBlue
|
||
|
// label.lineBreakMode = .byTruncatingTail
|
||
|
// row.addSubview(label)
|
||
|
// label.autoPinTopToSuperviewMargin()
|
||
|
// label.autoPinBottomToSuperviewMargin()
|
||
|
// label.autoPinLeadingToSuperviewMargin(withInset: hMargin)
|
||
|
// label.autoPinTrailingToSuperviewMargin(withInset: hMargin)
|
||
|
//
|
||
|
// return row
|
||
|
// }
|
||
|
|
||
|
// private func createNameValueRow(name: String, value: String, actionBlock : @escaping () -> Void) -> UIView {
|
||
|
// let row = TappableView(actionBlock: actionBlock)
|
||
|
// row.layoutMargins.left = 0
|
||
|
// row.layoutMargins.right = 0
|
||
|
//
|
||
|
// let nameLabel = UILabel()
|
||
|
// nameLabel.text = name
|
||
|
// nameLabel.font = UIFont.ows_dynamicTypeCaption1
|
||
|
// nameLabel.textColor = UIColor.black
|
||
|
// nameLabel.lineBreakMode = .byTruncatingTail
|
||
|
// row.addSubview(nameLabel)
|
||
|
// nameLabel.autoPinTopToSuperviewMargin()
|
||
|
// nameLabel.autoPinLeadingToSuperviewMargin(withInset: hMargin)
|
||
|
// nameLabel.autoPinTrailingToSuperviewMargin(withInset: hMargin)
|
||
|
//
|
||
|
// let valueLabel = UILabel()
|
||
|
// valueLabel.text = value
|
||
|
// valueLabel.font = UIFont.ows_dynamicTypeCaption1
|
||
|
// valueLabel.textColor = UIColor.ows_materialBlue
|
||
|
// valueLabel.lineBreakMode = .byTruncatingTail
|
||
|
// row.addSubview(valueLabel)
|
||
|
// valueLabel.autoPinEdge(.top, to: .bottom, of: nameLabel, withOffset: 3)
|
||
|
// valueLabel.autoPinBottomToSuperviewMargin()
|
||
|
// valueLabel.autoPinLeadingToSuperviewMargin(withInset: hMargin)
|
||
|
// valueLabel.autoPinTrailingToSuperviewMargin(withInset: hMargin)
|
||
|
//
|
||
|
// // TODO: Should there be a disclosure icon here?
|
||
|
//
|
||
|
// return row
|
||
|
// }
|
||
|
|
||
|
// // TODO: Use real assets.
|
||
|
// private func createCircleActionButton(text: String, actionBlock : @escaping () -> Void) -> UIView {
|
||
|
// let buttonSize = CGFloat(50)
|
||
|
//
|
||
|
// let button = TappableView(actionBlock: actionBlock)
|
||
|
// button.layoutMargins = .zero
|
||
|
// button.autoSetDimension(.width, toSize: buttonSize, relation: .greaterThanOrEqual)
|
||
|
//
|
||
|
// let circleView = UIView()
|
||
|
// circleView.backgroundColor = UIColor.white
|
||
|
// circleView.autoSetDimension(.width, toSize: buttonSize)
|
||
|
// circleView.autoSetDimension(.height, toSize: buttonSize)
|
||
|
// circleView.layer.cornerRadius = buttonSize * 0.5
|
||
|
// button.addSubview(circleView)
|
||
|
// circleView.autoPinEdge(toSuperviewEdge: .top)
|
||
|
// circleView.autoHCenterInSuperview()
|
||
|
//
|
||
|
// let label = UILabel()
|
||
|
// label.text = text
|
||
|
// label.font = UIFont.ows_dynamicTypeCaption2
|
||
|
// label.textColor = UIColor.black
|
||
|
// label.lineBreakMode = .byTruncatingTail
|
||
|
// label.textAlignment = .center
|
||
|
// button.addSubview(label)
|
||
|
// label.autoPinEdge(.top, to: .bottom, of: circleView, withOffset: 3)
|
||
|
// label.autoPinEdge(toSuperviewEdge: .bottom)
|
||
|
// label.autoPinLeadingToSuperviewMargin()
|
||
|
// label.autoPinTrailingToSuperviewMargin()
|
||
|
//
|
||
|
// return button
|
||
|
// }
|
||
|
|
||
|
// private func createLargePillButton(text: String, actionBlock : @escaping () -> Void) -> UIView {
|
||
|
// let button = TappableView(actionBlock: actionBlock)
|
||
|
// button.backgroundColor = UIColor.white
|
||
|
// button.layoutMargins = .zero
|
||
|
// button.autoSetDimension(.height, toSize: 45)
|
||
|
// button.layer.cornerRadius = 5
|
||
|
//
|
||
|
// let label = UILabel()
|
||
|
// label.text = text
|
||
|
// label.font = UIFont.ows_dynamicTypeCaption1
|
||
|
// label.textColor = UIColor.ows_materialBlue
|
||
|
// label.lineBreakMode = .byTruncatingTail
|
||
|
// label.textAlignment = .center
|
||
|
// button.addSubview(label)
|
||
|
// label.autoPinLeadingToSuperviewMargin(withInset: 20)
|
||
|
// label.autoPinTrailingToSuperviewMargin(withInset: 20)
|
||
|
// label.autoVCenterInSuperview()
|
||
|
// label.autoPinEdge(toSuperviewEdge: .top, withInset: 0, relation: .greaterThanOrEqual)
|
||
|
// label.autoPinEdge(toSuperviewEdge: .bottom, withInset: 0, relation: .greaterThanOrEqual)
|
||
|
//
|
||
|
// return button
|
||
|
// }
|
||
|
|
||
|
// private func createLabeledFieldRow(name: String, value: String, actionBlock : @escaping () -> Void) -> UIView {
|
||
|
// let row = TappableView(actionBlock: actionBlock)
|
||
|
// row.layoutMargins.left = 0
|
||
|
// row.layoutMargins.right = 0
|
||
|
//
|
||
|
// let nameLabel = UILabel()
|
||
|
// nameLabel.text = name
|
||
|
// nameLabel.font = UIFont.ows_dynamicTypeCaption1
|
||
|
// nameLabel.textColor = UIColor.black
|
||
|
// nameLabel.lineBreakMode = .byTruncatingTail
|
||
|
// row.addSubview(nameLabel)
|
||
|
// nameLabel.autoPinTopToSuperviewMargin()
|
||
|
// nameLabel.autoPinLeadingToSuperviewMargin(withInset: hMargin)
|
||
|
// nameLabel.autoPinTrailingToSuperviewMargin(withInset: hMargin)
|
||
|
//
|
||
|
// let valueLabel = UILabel()
|
||
|
// valueLabel.text = value
|
||
|
// valueLabel.font = UIFont.ows_dynamicTypeCaption1
|
||
|
// valueLabel.textColor = UIColor.ows_materialBlue
|
||
|
// valueLabel.lineBreakMode = .byTruncatingTail
|
||
|
// row.addSubview(valueLabel)
|
||
|
// valueLabel.autoPinEdge(.top, to: .bottom, of: nameLabel, withOffset: 3)
|
||
|
// valueLabel.autoPinBottomToSuperviewMargin()
|
||
|
// valueLabel.autoPinLeadingToSuperviewMargin(withInset: hMargin)
|
||
|
// valueLabel.autoPinTrailingToSuperviewMargin(withInset: hMargin)
|
||
|
//
|
||
|
// // TODO: Should there be a disclosure icon here?
|
||
|
//
|
||
|
// return row
|
||
|
// }
|
||
|
|
||
|
func previewView(forPhoneNumber phoneNumber: OWSContactPhoneNumber) -> UIView {
|
||
|
let label = UILabel()
|
||
|
label.text = PhoneNumber.bestEffortFormatE164(asLocalizedPhoneNumber: phoneNumber.phoneNumber)
|
||
|
label.font = UIFont.ows_dynamicTypeCaption1
|
||
|
label.textColor = UIColor.ows_materialBlue
|
||
|
label.lineBreakMode = .byTruncatingTail
|
||
|
// label.textAlignment = .center
|
||
|
return label
|
||
|
}
|
||
|
|
||
|
func previewView(forEmail email: OWSContactEmail) -> UIView {
|
||
|
let label = UILabel()
|
||
|
label.text = email.email
|
||
|
label.font = UIFont.ows_dynamicTypeCaption1
|
||
|
label.textColor = UIColor.ows_materialBlue
|
||
|
label.lineBreakMode = .byTruncatingTail
|
||
|
// label.textAlignment = .center
|
||
|
return label
|
||
|
}
|
||
|
|
||
|
func previewView(forAddress address: OWSContactAddress) -> UIView {
|
||
|
let previewView = UIView.container()
|
||
|
var lastRow: UIView?
|
||
|
let addRow: ((UIView) -> Void) = { (row) in
|
||
|
previewView.addSubview(row)
|
||
|
row.autoPinLeadingToSuperviewMargin()
|
||
|
row.autoPinTrailingToSuperviewMargin()
|
||
|
if let lastRow = lastRow {
|
||
|
row.autoPinEdge(.top, to: .bottom, of: lastRow, withOffset: 0)
|
||
|
} else {
|
||
|
row.autoPinEdge(toSuperviewEdge: .top, withInset: 0)
|
||
|
}
|
||
|
lastRow = row
|
||
|
}
|
||
|
let tryToAddNameValue: ((String, String?) -> Void) = { (name, value) in
|
||
|
guard let value = value else {
|
||
|
return
|
||
|
}
|
||
|
guard value.count > 0 else {
|
||
|
return
|
||
|
}
|
||
|
let row = UIView.container()
|
||
|
|
||
|
let nameLabel = UILabel()
|
||
|
nameLabel.text = name
|
||
|
nameLabel.font = UIFont.ows_dynamicTypeCaption1
|
||
|
nameLabel.textColor = UIColor.black
|
||
|
nameLabel.lineBreakMode = .byTruncatingTail
|
||
|
row.addSubview(nameLabel)
|
||
|
nameLabel.autoPinLeadingToSuperviewMargin()
|
||
|
nameLabel.autoPinHeightToSuperview()
|
||
|
nameLabel.setContentHuggingHigh()
|
||
|
nameLabel.setCompressionResistanceHigh()
|
||
|
|
||
|
let valueLabel = UILabel()
|
||
|
valueLabel.text = value
|
||
|
valueLabel.font = UIFont.ows_dynamicTypeCaption1
|
||
|
valueLabel.textColor = UIColor.ows_materialBlue
|
||
|
valueLabel.lineBreakMode = .byTruncatingTail
|
||
|
row.addSubview(valueLabel)
|
||
|
valueLabel.autoPinLeading(toTrailingEdgeOf: nameLabel, offset: 10)
|
||
|
valueLabel.autoPinTrailingToSuperviewMargin()
|
||
|
valueLabel.autoPinHeightToSuperview()
|
||
|
|
||
|
addRow(row)
|
||
|
}
|
||
|
|
||
|
tryToAddNameValue(NSLocalizedString("CONTACT_FIELD_ADDRESS_STREET", comment: "Label for the 'street' field of a contact's address."),
|
||
|
address.street)
|
||
|
tryToAddNameValue(NSLocalizedString("CONTACT_FIELD_ADDRESS_POBOX", comment: "Label for the 'pobox' field of a contact's address."),
|
||
|
address.pobox)
|
||
|
tryToAddNameValue(NSLocalizedString("CONTACT_FIELD_ADDRESS_NEIGHBORHOOD", comment: "Label for the 'neighborhood' field of a contact's address."),
|
||
|
address.neighborhood)
|
||
|
tryToAddNameValue(NSLocalizedString("CONTACT_FIELD_ADDRESS_CITY", comment: "Label for the 'city' field of a contact's address."),
|
||
|
address.city)
|
||
|
tryToAddNameValue(NSLocalizedString("CONTACT_FIELD_ADDRESS_REGION", comment: "Label for the 'region' field of a contact's address."),
|
||
|
address.region)
|
||
|
tryToAddNameValue(NSLocalizedString("CONTACT_FIELD_ADDRESS_POSTCODE", comment: "Label for the 'postcode' field of a contact's address."),
|
||
|
address.postcode)
|
||
|
tryToAddNameValue(NSLocalizedString("CONTACT_FIELD_ADDRESS_COUNTRY", comment: "Label for the 'country' field of a contact's address."),
|
||
|
address.country)
|
||
|
|
||
|
lastRow?.autoPinEdge(toSuperviewEdge: .bottom, withInset: 0)
|
||
|
|
||
|
return previewView
|
||
|
}
|
||
|
|
||
|
// MARK: -
|
||
|
|
||
|
// func didPressCreateNewContact(sender: UIGestureRecognizer) {
|
||
|
// Logger.info("\(self.TAG) \(#function)")
|
||
|
//
|
||
|
// guard sender.state == .recognized else {
|
||
|
// return
|
||
|
// }
|
||
|
// presentNewContactView()
|
||
|
// }
|
||
|
//
|
||
|
// func didPressAddToExistingContact(sender: UIGestureRecognizer) {
|
||
|
// Logger.info("\(self.TAG) \(#function)")
|
||
|
//
|
||
|
// guard sender.state == .recognized else {
|
||
|
// return
|
||
|
// }
|
||
|
// presentSelectAddToExistingContactView()
|
||
|
// }
|
||
|
//
|
||
|
// func didPressShareContact(sender: UIGestureRecognizer) {
|
||
|
// Logger.info("\(self.TAG) \(#function)")
|
||
|
//
|
||
|
// guard sender.state == .recognized else {
|
||
|
// return
|
||
|
// }
|
||
|
// // TODO:
|
||
|
// }
|
||
|
//
|
||
|
// func didPressSendMessage() {
|
||
|
// Logger.info("\(self.TAG) \(#function)")
|
||
|
//
|
||
|
// presentThreadAndPeform(action: .compose)
|
||
|
// }
|
||
|
//
|
||
|
// func didPressAudioCall() {
|
||
|
// Logger.info("\(self.TAG) \(#function)")
|
||
|
//
|
||
|
// presentThreadAndPeform(action: .audioCall)
|
||
|
// }
|
||
|
//
|
||
|
// func didPressVideoCall() {
|
||
|
// Logger.info("\(self.TAG) \(#function)")
|
||
|
//
|
||
|
// presentThreadAndPeform(action: .videoCall)
|
||
|
// }
|
||
|
//
|
||
|
// func presentThreadAndPeform(action: ConversationViewAction) {
|
||
|
// // TODO: We're taking the first Signal account id. We might
|
||
|
// // want to let the user select if there's more than one.
|
||
|
// let phoneNumbers = systemContactsWithSignalAccountsForContact()
|
||
|
// guard phoneNumbers.count > 0 else {
|
||
|
// owsFail("\(logTag) missing Signal recipient id.")
|
||
|
// return
|
||
|
// }
|
||
|
// guard phoneNumbers.count > 1 else {
|
||
|
// let recipientId = systemContactsWithSignalAccountsForContact().first!
|
||
|
// SignalApp.shared().presentConversation(forRecipientId: recipientId, action: action)
|
||
|
// return
|
||
|
// }
|
||
|
//
|
||
|
// showPhoneNumberPicker(phoneNumbers: phoneNumbers, completion: { (recipientId) in
|
||
|
// SignalApp.shared().presentConversation(forRecipientId: recipientId, action: action)
|
||
|
// })
|
||
|
// }
|
||
|
//
|
||
|
// func didPressInvite() {
|
||
|
// Logger.info("\(self.TAG) \(#function)")
|
||
|
//
|
||
|
// guard MFMessageComposeViewController.canSendText() else {
|
||
|
// Logger.info("\(TAG) Device cannot send text")
|
||
|
// OWSAlerts.showErrorAlert(message: NSLocalizedString("UNSUPPORTED_FEATURE_ERROR", comment: ""))
|
||
|
// return
|
||
|
// }
|
||
|
// let phoneNumbers =
|
||
|
// phoneNumbersForContact()
|
||
|
// guard phoneNumbers.count > 0 else {
|
||
|
// owsFail("\(logTag) no phone numbers.")
|
||
|
// return
|
||
|
// }
|
||
|
//
|
||
|
// let inviteFlow =
|
||
|
// InviteFlow(presentingViewController: self, contactsManager: contactsManager)
|
||
|
// inviteFlow.sendSMSTo(phoneNumbers: phoneNumbers)
|
||
|
// }
|
||
|
//
|
||
|
// private func showPhoneNumberPicker(phoneNumbers: [String], completion :@escaping ((String) -> Void)) {
|
||
|
//
|
||
|
// let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||
|
//
|
||
|
// for phoneNumber in phoneNumbers {
|
||
|
// actionSheet.addAction(UIAlertAction(title: PhoneNumber.bestEffortFormatE164(asLocalizedPhoneNumber: phoneNumber),
|
||
|
// style: .default) { _ in
|
||
|
// completion(phoneNumber)
|
||
|
// })
|
||
|
// }
|
||
|
// actionSheet.addAction(OWSAlerts.cancelAction)
|
||
|
//
|
||
|
// self.present(actionSheet, animated: true)
|
||
|
// }
|
||
|
|
||
|
// func didPressDismiss() {
|
||
|
// Logger.info("\(self.TAG) \(#function)")
|
||
|
//
|
||
|
// self.navigationController?.popViewController(animated: true)
|
||
|
// }
|
||
|
|
||
|
func didPressSendButton() {
|
||
|
Logger.info("\(logTag) \(#function)")
|
||
|
|
||
|
// TODO:
|
||
|
}
|
||
|
}
|