Skip to content

Commit d53496a

Browse files
Merge pull request #363 from woocommerce/issue/362-fixing-ipad-crash
Fixing iPad Crash
2 parents c64958d + 6bfa103 commit d53496a

File tree

3 files changed

+93
-56
lines changed

3 files changed

+93
-56
lines changed

WooCommerce/Classes/Model/Address+Woo.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,22 @@ extension Address {
1919
return postalAddress.formatted(as: .mailingAddress)
2020
}
2121

22-
/// Returns the (clean) Phone number: contains only decimal digits
22+
/// Returns the (clean) Phone number: contains only decimal digits.
2323
///
2424
var cleanedPhoneNumber: String? {
2525
return phone?.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
2626
}
2727

28+
/// Returns the (Clean) Phone Number, as an iOS Actionable URL.
29+
///
30+
var cleanedPhoneNumberAsActionableURL: URL? {
31+
guard let phone = cleanedPhoneNumber else {
32+
return nil
33+
}
34+
35+
return URL(string: "telprompt://" + phone)
36+
}
37+
2838
/// Indicates if there is a Phone Number set (and it's not empty).
2939
///
3040
var hasPhoneNumber: Bool {

WooCommerce/Classes/ViewRelated/Orders/OrderDetails/BillingDetailsTableViewCell.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class BillingDetailsTableViewCell: UITableViewCell {
1616

1717
/// Closure to be executed whenever the cell is pressed.
1818
///
19-
var onTouchUp: (() -> Void)?
19+
var onTouchUp: ((UIView) -> Void)?
2020

2121

2222
// MARK: - Overridden Methods
@@ -31,7 +31,11 @@ class BillingDetailsTableViewCell: UITableViewCell {
3131

3232
let gestureRecognizer = UITapGestureRecognizer()
3333
gestureRecognizer.on { [weak self] gesture in
34-
self?.onTouchUp?()
34+
guard let `self` = self else {
35+
return
36+
}
37+
38+
self.onTouchUp?(self)
3539
}
3640

3741
addGestureRecognizer(gestureRecognizer)

WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift

Lines changed: 76 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,9 @@ private extension OrderDetailsViewController {
313313

314314
cell.textLabel?.text = email
315315
cell.accessoryImageView.image = Gridicon.iconOfType(.mail)
316-
cell.onTouchUp = { [weak self] in
317-
self?.emailButtonAction()
316+
cell.onTouchUp = { [weak self] _ in
317+
WooAnalytics.shared.track(.orderDetailCustomerEmailTapped)
318+
self?.displayEmailComposerIfPossible()
318319
}
319320

320321
cell.isAccessibilityElement = true
@@ -331,8 +332,8 @@ private extension OrderDetailsViewController {
331332

332333
cell.textLabel?.text = phoneNumber
333334
cell.accessoryImageView.image = Gridicon.iconOfType(.ellipsis)
334-
cell.onTouchUp = { [weak self] in
335-
self?.phoneButtonAction()
335+
cell.onTouchUp = { [weak self] sender in
336+
self?.displayContactCustomerAlert(from: sender)
336337
}
337338

338339
cell.isAccessibilityElement = true
@@ -485,42 +486,7 @@ private extension OrderDetailsViewController {
485486

486487
// MARK: - Actions
487488
//
488-
extension OrderDetailsViewController {
489-
@objc func phoneButtonAction() {
490-
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
491-
actionSheet.view.tintColor = StyleManager.wooCommerceBrandColor
492-
let dismissAction = UIAlertAction(title: NSLocalizedString("Dismiss", comment: "Dismiss the action sheet"), style: .cancel)
493-
actionSheet.addAction(dismissAction)
494-
495-
let callAction = UIAlertAction(title: NSLocalizedString("Call", comment: "Call phone number button title"), style: .default) { [weak self] action in
496-
WooAnalytics.shared.track(.orderDetailCustomerPhoneOptionTapped)
497-
guard let phone = self?.viewModel.order.billingAddress?.cleanedPhoneNumber else {
498-
return
499-
}
500-
if let url = URL(string: "telprompt://" + phone),
501-
UIApplication.shared.canOpenURL(url) {
502-
UIApplication.shared.open(url, options: [:], completionHandler: nil)
503-
WooAnalytics.shared.track(.orderContactAction, withProperties: ["id": self?.viewModel.order.orderID ?? 0,
504-
"status": self?.viewModel.order.status.rawValue ?? String(),
505-
"type": "call"])
506-
}
507-
}
508-
actionSheet.addAction(callAction)
509-
510-
let messageAction = UIAlertAction(title: NSLocalizedString("Message", comment: "Message phone number button title"), style: .default) { [weak self] action in
511-
WooAnalytics.shared.track(.orderDetailCustomerSMSOptionTapped)
512-
self?.sendTextMessageIfPossible()
513-
}
514-
515-
actionSheet.addAction(messageAction)
516-
WooAnalytics.shared.track(.orderDetailCustomerPhoneMenuTapped)
517-
present(actionSheet, animated: true)
518-
}
519-
520-
@objc func emailButtonAction() {
521-
WooAnalytics.shared.track(.orderDetailCustomerEmailTapped)
522-
sendEmailIfPossible()
523-
}
489+
private extension OrderDetailsViewController {
524490

525491
func toggleBillingFooter() {
526492
displaysBillingDetails = !displaysBillingDetails
@@ -642,23 +608,73 @@ extension OrderDetailsViewController: UITableViewDelegate {
642608
}
643609

644610

645-
// MARK: - MFMessageComposeViewControllerDelegate Conformance
611+
// MARK: - Contact Alert
646612
//
647-
extension OrderDetailsViewController: MFMessageComposeViewControllerDelegate {
648-
func sendTextMessageIfPossible() {
649-
guard let phoneNumber = viewModel.order.billingAddress?.cleanedPhoneNumber else {
613+
private extension OrderDetailsViewController {
614+
615+
/// Displays an alert that offers several contact methods to reach the customer: [Phone / Message]
616+
///
617+
func displayContactCustomerAlert(from sourceView: UIView) {
618+
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
619+
actionSheet.view.tintColor = StyleManager.wooCommerceBrandColor
620+
621+
actionSheet.addCancelActionWithTitle(ContactAction.dismiss)
622+
actionSheet.addDefaultActionWithTitle(ContactAction.call) { [weak self] _ in
623+
guard let phoneURL = self?.viewModel.order.billingAddress?.cleanedPhoneNumberAsActionableURL else {
624+
return
625+
}
626+
627+
WooAnalytics.shared.track(.orderDetailCustomerPhoneOptionTapped)
628+
self?.callCustomerIfPossible(at: phoneURL)
629+
}
630+
631+
actionSheet.addDefaultActionWithTitle(ContactAction.message) { [weak self] _ in
632+
WooAnalytics.shared.track(.orderDetailCustomerSMSOptionTapped)
633+
self?.displayMessageComposerIfPossible()
634+
}
635+
636+
let popoverController = actionSheet.popoverPresentationController
637+
popoverController?.sourceView = sourceView
638+
popoverController?.sourceRect = sourceView.bounds
639+
640+
present(actionSheet, animated: true)
641+
642+
WooAnalytics.shared.track(.orderDetailCustomerPhoneMenuTapped)
643+
}
644+
645+
/// Attempts to perform a phone call at the specified URL
646+
///
647+
func callCustomerIfPossible(at phoneURL: URL) {
648+
guard UIApplication.shared.canOpenURL(phoneURL) else {
650649
return
651650
}
652651

653-
if MFMessageComposeViewController.canSendText() {
654-
sendTextMessage(to: phoneNumber)
655-
WooAnalytics.shared.track(.orderContactAction, withProperties: ["id": viewModel.order.orderID,
656-
"status": viewModel.order.status.rawValue,
657-
"type": "sms"])
652+
UIApplication.shared.open(phoneURL, options: [:], completionHandler: nil)
653+
WooAnalytics.shared.track(.orderContactAction, withProperties: ["id": self.viewModel.order.orderID,
654+
"status": self.viewModel.order.status.rawValue,
655+
"type": "call"])
656+
657+
}
658+
}
659+
660+
661+
// MARK: - MFMessageComposeViewControllerDelegate Conformance
662+
//
663+
extension OrderDetailsViewController: MFMessageComposeViewControllerDelegate {
664+
func displayMessageComposerIfPossible() {
665+
guard let phoneNumber = viewModel.order.billingAddress?.cleanedPhoneNumber,
666+
MFMessageComposeViewController.canSendText()
667+
else {
668+
return
658669
}
670+
671+
displayMessageComposer(for: phoneNumber)
672+
WooAnalytics.shared.track(.orderContactAction, withProperties: ["id": viewModel.order.orderID,
673+
"status": viewModel.order.status.rawValue,
674+
"type": "sms"])
659675
}
660676

661-
private func sendTextMessage(to phoneNumber: String) {
677+
private func displayMessageComposer(for phoneNumber: String) {
662678
let controller = MFMessageComposeViewController()
663679
controller.recipients = [phoneNumber]
664680
controller.messageComposeDelegate = self
@@ -674,18 +690,18 @@ extension OrderDetailsViewController: MFMessageComposeViewControllerDelegate {
674690
// MARK: - MFMailComposeViewControllerDelegate Conformance
675691
//
676692
extension OrderDetailsViewController: MFMailComposeViewControllerDelegate {
677-
func sendEmailIfPossible() {
693+
func displayEmailComposerIfPossible() {
678694
guard let email = viewModel.order.billingAddress?.email, MFMailComposeViewController.canSendMail() else {
679695
return
680696
}
681697

682-
sendEmail(to: email)
698+
displayEmailComposer(for: email)
683699
WooAnalytics.shared.track(.orderContactAction, withProperties: ["id": viewModel.order.orderID,
684700
"status": viewModel.order.status.rawValue,
685701
"type": "email"])
686702
}
687703

688-
private func sendEmail(to email: String) {
704+
private func displayEmailComposer(for email: String) {
689705
// Workaround: MFMailCompose isn't *FULLY* picking up UINavigationBar's WC's appearance. Title / Buttons look awful.
690706
// We're falling back to iOS's default appearance
691707
UINavigationBar.applyDefaultAppearance()
@@ -709,6 +725,13 @@ extension OrderDetailsViewController: MFMailComposeViewControllerDelegate {
709725
// MARK: - Constants
710726
//
711727
private extension OrderDetailsViewController {
728+
729+
enum ContactAction {
730+
static let dismiss = NSLocalizedString("Dismiss", comment: "Dismiss the action sheet")
731+
static let call = NSLocalizedString("Call", comment: "Call phone number button title")
732+
static let message = NSLocalizedString("Message", comment: "Message phone number button title")
733+
}
734+
712735
enum Constants {
713736
static let rowHeight = CGFloat(38)
714737
static let sectionHeight = CGFloat(44)

0 commit comments

Comments
 (0)