@@ -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//
676692extension 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//
711727private 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