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.
		
		
		
		
		
			
		
			
				
	
	
		
			334 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Swift
		
	
			
		
		
	
	
			334 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Swift
		
	
| //
 | |
| //  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()
 | |
|     }
 | |
| 
 | |
|     private let hMargin = CGFloat(16)
 | |
|     private let vMargin = CGFloat(10)
 | |
| 
 | |
|     func createContents() {
 | |
|         self.layoutMargins = UIEdgeInsets(top: vMargin, left: hMargin, bottom: vMargin, right: hMargin)
 | |
| 
 | |
|         let stackView = UIStackView()
 | |
|         stackView.axis = .horizontal
 | |
|         stackView.alignment = .center
 | |
|         stackView.layoutMargins = .zero
 | |
|         stackView.spacing = 10
 | |
|         self.addSubview(stackView)
 | |
|         stackView.autoPinEdgesToSuperviewMargins()
 | |
| 
 | |
|         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 = Theme.primaryColor
 | |
|         stackView.addArrangedSubview(valueView)
 | |
| 
 | |
|         valueView.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
 | |
|     }
 | |
| 
 | |
|     @objc func wasTapped(sender: UIGestureRecognizer) {
 | |
|         Logger.info("\(self.logTag) \(#function)")
 | |
| 
 | |
|         guard sender.state == .recognized else {
 | |
|             return
 | |
|         }
 | |
| 
 | |
|         valueView.becomeFirstResponder()
 | |
|     }
 | |
| 
 | |
|     @objc 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: ContactShareViewModel)
 | |
| }
 | |
| 
 | |
| // MARK: -
 | |
| 
 | |
| @objc
 | |
| public class EditContactShareNameViewController: OWSViewController, ContactNameFieldViewDelegate {
 | |
|     weak var delegate: EditContactShareNameViewControllerDelegate?
 | |
| 
 | |
|     let contactShare: ContactShareViewModel
 | |
| 
 | |
|     var namePrefixView: ContactNameFieldView!
 | |
|     var givenNameView: ContactNameFieldView!
 | |
|     var middleNameView: ContactNameFieldView!
 | |
|     var familyNameView: ContactNameFieldView!
 | |
|     var nameSuffixView: ContactNameFieldView!
 | |
|     var organizationNameView: 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: ContactShareViewModel, 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.name.namePrefix, delegate: self)
 | |
|         givenNameView = ContactNameFieldView(name: NSLocalizedString("CONTACT_FIELD_GIVEN_NAME",
 | |
|                                                                      comment: "Label for the 'given name' field of a contact."),
 | |
|                                              value: contactShare.name.givenName, delegate: self)
 | |
|         middleNameView = ContactNameFieldView(name: NSLocalizedString("CONTACT_FIELD_MIDDLE_NAME",
 | |
|                                                                       comment: "Label for the 'middle name' field of a contact."),
 | |
|                                               value: contactShare.name.middleName, delegate: self)
 | |
|         familyNameView = ContactNameFieldView(name: NSLocalizedString("CONTACT_FIELD_FAMILY_NAME",
 | |
|                                                                       comment: "Label for the 'family name' field of a contact."),
 | |
|                                               value: contactShare.name.familyName, delegate: self)
 | |
|         nameSuffixView = ContactNameFieldView(name: NSLocalizedString("CONTACT_FIELD_NAME_SUFFIX",
 | |
|                                                                       comment: "Label for the 'name suffix' field of a contact."),
 | |
|                                               value: contactShare.name.nameSuffix, delegate: self)
 | |
|         organizationNameView = ContactNameFieldView(name: NSLocalizedString("CONTACT_FIELD_ORGANIZATION",
 | |
|                                                                             comment: "Label for the 'organization' field of a contact."),
 | |
|                                               value: contactShare.name.organizationName, delegate: self)
 | |
|         fieldViews = [
 | |
|             namePrefixView ,
 | |
|             givenNameView ,
 | |
|             middleNameView ,
 | |
|             familyNameView ,
 | |
|             nameSuffixView,
 | |
|             organizationNameView
 | |
|         ]
 | |
|     }
 | |
| 
 | |
|     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 = Theme.backgroundColor
 | |
| 
 | |
|         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()
 | |
| 
 | |
|         scrollView.addSubview(fieldsView)
 | |
|         fieldsView.autoPinLeadingToSuperviewMargin()
 | |
|         fieldsView.autoPinTrailingToSuperviewMargin()
 | |
|         fieldsView.autoPinEdge(toSuperviewEdge: .top)
 | |
|         fieldsView.autoPinEdge(toSuperviewEdge: .bottom)
 | |
|     }
 | |
| 
 | |
|     private func createFieldsView() -> UIView {
 | |
|         SwiftAssertIsOnMainThread(#function)
 | |
| 
 | |
|         var rows = [UIView]()
 | |
| 
 | |
|         for fieldView in fieldViews {
 | |
|             rows.append(fieldView)
 | |
|         }
 | |
| 
 | |
|         return ContactFieldView(rows: rows, hMargin: hMargin)
 | |
|     }
 | |
| 
 | |
|     private let hMargin = CGFloat(16)
 | |
| 
 | |
|     // MARK: -
 | |
| 
 | |
|     @objc func didPressSave() {
 | |
|         Logger.info("\(logTag) \(#function)")
 | |
| 
 | |
|         guard let newName = OWSContactName() else {
 | |
|             owsFail("\(logTag) could not create a new name.")
 | |
|             return
 | |
|         }
 | |
|         newName.namePrefix = namePrefixView.value().ows_stripped()
 | |
|         newName.givenName = givenNameView.value().ows_stripped()
 | |
|         newName.middleName = middleNameView.value().ows_stripped()
 | |
|         newName.familyName = familyNameView.value().ows_stripped()
 | |
|         newName.nameSuffix = nameSuffixView.value().ows_stripped()
 | |
|         newName.organizationName = organizationNameView.value().ows_stripped()
 | |
| 
 | |
|         let modifiedContactShare = contactShare.copy(withName: newName)
 | |
| 
 | |
|         guard let delegate = self.delegate else {
 | |
|             owsFail("\(logTag) missing delegate.")
 | |
|             return
 | |
|         }
 | |
| 
 | |
|         delegate.editContactShareNameView(self, didEditContactShare: modifiedContactShare)
 | |
| 
 | |
|         guard let navigationController = self.navigationController else {
 | |
|             owsFail("\(logTag) Missing navigationController.")
 | |
|             return
 | |
|         }
 | |
|         navigationController.popViewController(animated: true)
 | |
|     }
 | |
| 
 | |
|     @objc func didPressCancel() {
 | |
|         Logger.info("\(logTag) \(#function)")
 | |
| 
 | |
|         guard let navigationController = self.navigationController else {
 | |
|             owsFail("\(logTag) Missing navigationController.")
 | |
|             return
 | |
|         }
 | |
|         navigationController.popViewController(animated: true)
 | |
|     }
 | |
| 
 | |
|     // MARK: - ContactNameFieldViewDelegate
 | |
| 
 | |
|     public func nameFieldDidChange() {
 | |
|         updateNavigationBar()
 | |
|     }
 | |
| }
 |