From b4d24f1c7246afe1cd6821013f51eb70d0b31a12 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 9 May 2018 14:26:51 -0400 Subject: [PATCH 1/2] Refine field actions in contact view. --- .../ContactViewController.swift | 143 +++++++++++++++--- .../src/Messages/Interactions/OWSContact.h | 2 + .../src/Messages/Interactions/OWSContact.m | 13 ++ 3 files changed, 133 insertions(+), 25 deletions(-) diff --git a/Signal/src/ViewControllers/ContactViewController.swift b/Signal/src/ViewControllers/ContactViewController.swift index dace808343..aa577ca15c 100644 --- a/Signal/src/ViewControllers/ContactViewController.swift +++ b/Signal/src/ViewControllers/ContactViewController.swift @@ -358,24 +358,18 @@ class ContactViewController: OWSViewController, ContactShareViewHelperDelegate { for phoneNumber in contactShare.phoneNumbers { rows.append(ContactFieldView.contactFieldView(forPhoneNumber: phoneNumber, layoutMargins: UIEdgeInsets(top: 5, left: hMargin, bottom: 5, right: hMargin), - 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) + actionBlock: { [weak self] _ in + guard let strongSelf = self else { return } + strongSelf.didPressPhoneNumber(phoneNumber: phoneNumber) })) } for email in contactShare.emails { rows.append(ContactFieldView.contactFieldView(forEmail: email, layoutMargins: UIEdgeInsets(top: 5, left: hMargin, bottom: 5, right: hMargin), - actionBlock: { - guard let url = NSURL(string: "mailto:\(email.email)") else { - owsFail("\(ContactViewController.logTag) could not open email.") - return - } - UIApplication.shared.openURL(url as URL) + actionBlock: { [weak self] _ in + guard let strongSelf = self else { return } + strongSelf.didPressEmail(email: email) })) } @@ -527,9 +521,120 @@ class ContactViewController: OWSViewController, ContactShareViewHelperDelegate { navigationController.popViewController(animated: true) } + func didPressPhoneNumber(phoneNumber: OWSContactPhoneNumber) { + Logger.info("\(self.logTag) \(#function)") + + let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) + + if let e164 = phoneNumber.tryToConvertToE164() { + if contactShare.systemContactsWithSignalAccountPhoneNumbers(contactsManager).contains(e164) { + actionSheet.addAction(UIAlertAction(title: NSLocalizedString("ACTION_SEND_MESSAGE", + comment: "Label for 'sent message' button in contact view."), + style: .default) { _ in + SignalApp.shared().presentConversation(forRecipientId: e164, action: .compose) + }) + actionSheet.addAction(UIAlertAction(title: NSLocalizedString("ACTION_AUDIO_CALL", + comment: "Label for 'audio call' button in contact view."), + style: .default) { _ in + SignalApp.shared().presentConversation(forRecipientId: e164, action: .audioCall) + }) + actionSheet.addAction(UIAlertAction(title: NSLocalizedString("ACTION_VIDEO_CALL", + comment: "Label for 'video call' button in contact view."), + style: .default) { _ in + SignalApp.shared().presentConversation(forRecipientId: e164, action: .videoCall) + }) + } else { + // TODO: We could offer callPhoneNumberWithSystemCall. + } + } + actionSheet.addAction(UIAlertAction(title: NSLocalizedString("EDIT_ITEM_COPY_ACTION", + comment: "Short name for edit menu item to copy contents of media message."), + style: .default) { _ in + UIPasteboard.general.string = phoneNumber.phoneNumber + }) + actionSheet.addAction(OWSAlerts.cancelAction) + present(actionSheet, animated: true) + } + + func callPhoneNumberWithSystemCall(phoneNumber: OWSContactPhoneNumber) { + Logger.info("\(self.logTag) \(#function)") + + guard let url = NSURL(string: "tel:\(phoneNumber.phoneNumber)") else { + owsFail("\(ContactViewController.logTag) could not open phone number.") + return + } + UIApplication.shared.openURL(url as URL) + } + + func didPressEmail(email: OWSContactEmail) { + Logger.info("\(self.logTag) \(#function)") + + let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) + actionSheet.addAction(UIAlertAction(title: NSLocalizedString("CONTACT_VIEW_OPEN_ADDRESS_IN_MAPS_APP", + comment: "Label for 'open email in email app' button in contact view."), + style: .default) { [weak self] _ in + self?.openEmailInEmailApp(email: email) + }) + actionSheet.addAction(UIAlertAction(title: NSLocalizedString("EDIT_ITEM_COPY_ACTION", + comment: "Short name for edit menu item to copy contents of media message."), + style: .default) { _ in + UIPasteboard.general.string = email.email + }) + actionSheet.addAction(OWSAlerts.cancelAction) + present(actionSheet, animated: true) + } + + func openEmailInEmailApp(email: OWSContactEmail) { + Logger.info("\(self.logTag) \(#function)") + + guard let url = NSURL(string: "mailto:\(email.email)") else { + owsFail("\(ContactViewController.logTag) could not open email.") + return + } + UIApplication.shared.openURL(url as URL) + } + func didPressAddress(address: OWSContactAddress) { Logger.info("\(self.logTag) \(#function)") + let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) + actionSheet.addAction(UIAlertAction(title: NSLocalizedString("CONTACT_VIEW_OPEN_ADDRESS_IN_MAPS_APP", + comment: "Label for 'open address in maps app' button in contact view."), + style: .default) { [weak self] _ in + self?.openAddressInMaps(address: address) + }) + actionSheet.addAction(UIAlertAction(title: NSLocalizedString("EDIT_ITEM_COPY_ACTION", + comment: "Short name for edit menu item to copy contents of media message."), + style: .default) { [weak self] _ in + guard let strongSelf = self else { return } + + UIPasteboard.general.string = strongSelf.formatAddressForQuery(address: address) + }) + actionSheet.addAction(OWSAlerts.cancelAction) + present(actionSheet, animated: true) + } + + func openAddressInMaps(address: OWSContactAddress) { + Logger.info("\(self.logTag) \(#function)") + + let mapAddress = formatAddressForQuery(address: address) + guard let escapedMapAddress = mapAddress.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { + owsFail("\(ContactViewController.logTag) could not open address.") + return + } + // Note that we use "q" (i.e. query) rather than "address" since we can't assume + // this is a well-formed address. + guard let url = URL(string: "http://maps.apple.com/?q=\(escapedMapAddress)") else { + owsFail("\(ContactViewController.logTag) could not open address.") + return + } + + UIApplication.shared.openURL(url as URL) + } + + func formatAddressForQuery(address: OWSContactAddress) -> String { + Logger.info("\(self.logTag) \(#function)") + // Open address in Apple Maps app. var addressParts = [String]() let addAddressPart: ((String?) -> Void) = { (part) in @@ -547,19 +652,7 @@ class ContactViewController: OWSViewController, ContactShareViewHelperDelegate { addAddressPart(address.region) addAddressPart(address.postcode) addAddressPart(address.country) - let mapAddress = addressParts.joined(separator: ", ") - guard let escapedMapAddress = mapAddress.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { - owsFail("\(ContactViewController.logTag) could not open address.") - return - } - // Note that we use "q" (i.e. query) rather than "address" since we can't assume - // this is a well-formed address. - guard let url = URL(string: "http://maps.apple.com/?q=\(escapedMapAddress)") else { - owsFail("\(ContactViewController.logTag) could not open address.") - return - } - - UIApplication.shared.openURL(url as URL) + return addressParts.joined(separator: ", ") } // MARK: - ContactShareViewHelperDelegate diff --git a/SignalServiceKit/src/Messages/Interactions/OWSContact.h b/SignalServiceKit/src/Messages/Interactions/OWSContact.h index c8199d1c2b..91058668a2 100644 --- a/SignalServiceKit/src/Messages/Interactions/OWSContact.h +++ b/SignalServiceKit/src/Messages/Interactions/OWSContact.h @@ -48,6 +48,8 @@ NSString *NSStringForContactPhoneType(OWSContactPhoneType value); @property (nonatomic, readonly) NSString *phoneNumber; +- (nullable NSString *)tryToConvertToE164; + @end #pragma mark - diff --git a/SignalServiceKit/src/Messages/Interactions/OWSContact.m b/SignalServiceKit/src/Messages/Interactions/OWSContact.m index 3d33d603cf..6131fda325 100644 --- a/SignalServiceKit/src/Messages/Interactions/OWSContact.m +++ b/SignalServiceKit/src/Messages/Interactions/OWSContact.m @@ -90,6 +90,19 @@ NSString *NSStringForContactPhoneType(OWSContactPhoneType value) return result; } +- (nullable NSString *)tryToConvertToE164 +{ + PhoneNumber *_Nullable parsedPhoneNumber; + parsedPhoneNumber = [PhoneNumber tryParsePhoneNumberFromE164:self.phoneNumber]; + if (!parsedPhoneNumber) { + parsedPhoneNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:self.phoneNumber]; + } + if (parsedPhoneNumber) { + return parsedPhoneNumber.toE164; + } + return nil; +} + @end #pragma mark - From 65a516685dadca98e6116bff6a37304dde97c4a2 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 9 May 2018 14:36:05 -0400 Subject: [PATCH 2/2] Fix l10n strings. --- Signal/src/ViewControllers/ContactViewController.swift | 2 +- Signal/translations/en.lproj/Localizable.strings | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Signal/src/ViewControllers/ContactViewController.swift b/Signal/src/ViewControllers/ContactViewController.swift index aa577ca15c..9f8dbe9d35 100644 --- a/Signal/src/ViewControllers/ContactViewController.swift +++ b/Signal/src/ViewControllers/ContactViewController.swift @@ -570,7 +570,7 @@ class ContactViewController: OWSViewController, ContactShareViewHelperDelegate { Logger.info("\(self.logTag) \(#function)") let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) - actionSheet.addAction(UIAlertAction(title: NSLocalizedString("CONTACT_VIEW_OPEN_ADDRESS_IN_MAPS_APP", + actionSheet.addAction(UIAlertAction(title: NSLocalizedString("CONTACT_VIEW_OPEN_EMAIL_IN_EMAIL_APP", comment: "Label for 'open email in email app' button in contact view."), style: .default) { [weak self] _ in self?.openEmailInEmailApp(email: email) diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 97a849f8d7..3a41f46ec1 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -484,6 +484,12 @@ /* Error indicating that at least one contact field must be selected before sharing a contact. */ "CONTACT_SHARE_NO_FIELDS_SELECTED" = "No contact fields selected."; +/* Label for 'open address in maps app' button in contact view. */ +"CONTACT_VIEW_OPEN_ADDRESS_IN_MAPS_APP" = "Open in Maps"; + +/* Label for 'open email in email app' button in contact view. */ +"CONTACT_VIEW_OPEN_EMAIL_IN_EMAIL_APP" = "Send Email"; + /* Indicates that a contact has no name. */ "CONTACT_WITHOUT_NAME" = "Unnamed Contact";