@@ -58,6 +58,10 @@ class OrderDetailsViewController: UIViewController {
5858 }
5959 }
6060
61+ /// Haptic Feedback!
62+ ///
63+ private let hapticGenerator = UINotificationFeedbackGenerator ( )
64+
6165
6266 // MARK: - View Lifecycle
6367
@@ -437,18 +441,6 @@ private extension OrderDetailsViewController {
437441
438442 cell. display ( orderStatus: viewModel. order. status)
439443 }
440-
441- // MARK: - Get order note
442- //
443- func note( at indexPath: IndexPath ) -> OrderNote ? {
444- // We need to subtract 1 here because the first order note row is the "Add Order" cell
445- let noteIndex = indexPath. row - 1
446- guard orderNotes. indices. contains ( noteIndex) else {
447- return nil
448- }
449-
450- return orderNotes [ noteIndex]
451- }
452444}
453445
454446
@@ -589,6 +581,7 @@ extension OrderDetailsViewController: UITableViewDataSource {
589581// MARK: - UITableViewDelegate Conformance
590582//
591583extension OrderDetailsViewController : UITableViewDelegate {
584+
592585 func tableView( _ tableView: UITableView , didSelectRowAt indexPath: IndexPath ) {
593586 tableView. deselectRow ( at: indexPath, animated: true )
594587
@@ -609,6 +602,51 @@ extension OrderDetailsViewController: UITableViewDelegate {
609602 }
610603 }
611604
605+ func tableView( _ tableView: UITableView , leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath ) -> UISwipeActionsConfiguration ? {
606+ guard checkIfCopyingIsAllowed ( for: indexPath) else {
607+ // Only allow the leading swipe action on the address rows
608+ return UISwipeActionsConfiguration ( actions: [ ] )
609+ }
610+
611+ let row = rowAtIndexPath ( indexPath)
612+ let copyActionTitle = NSLocalizedString ( " Copy " , comment: " Copy address text button title — should be one word and as short as possible. " )
613+ let copyAction = UIContextualAction ( style: . normal, title: copyActionTitle) { [ weak self] ( action, view, success) in
614+ self ? . copyText ( at: row)
615+ success ( true )
616+ }
617+ copyAction. backgroundColor = StyleManager . wooCommerceBrandColor
618+
619+ return UISwipeActionsConfiguration ( actions: [ copyAction] )
620+ }
621+
622+ func tableView( _ tableView: UITableView , trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath ) -> UISwipeActionsConfiguration ? {
623+ // No trailing action on any cell
624+ return UISwipeActionsConfiguration ( actions: [ ] )
625+ }
626+
627+ func tableView( _ tableView: UITableView , shouldShowMenuForRowAt indexPath: IndexPath ) -> Bool {
628+ return checkIfCopyingIsAllowed ( for: indexPath)
629+ }
630+
631+ func tableView( _ tableView: UITableView , canPerformAction action: Selector , forRowAt indexPath: IndexPath , withSender sender: Any ? ) -> Bool {
632+ return action == #selector( copy ( _: ) )
633+ }
634+
635+ func tableView( _ tableView: UITableView , performAction action: Selector , forRowAt indexPath: IndexPath , withSender sender: Any ? ) {
636+ guard action == #selector( copy ( _: ) ) else {
637+ return
638+ }
639+
640+ let row = rowAtIndexPath ( indexPath)
641+ copyText ( at: row)
642+ }
643+ }
644+
645+
646+ // MARK: - Segues
647+ //
648+ extension OrderDetailsViewController {
649+
612650 override func prepare( for segue: UIStoryboardSegue , sender: Any ? ) {
613651 if let productListViewController = segue. destination as? ProductListViewController {
614652 productListViewController. viewModel = viewModel
@@ -617,6 +655,79 @@ extension OrderDetailsViewController: UITableViewDelegate {
617655}
618656
619657
658+ // MARK: - Convenience Methods
659+ //
660+ private extension OrderDetailsViewController {
661+
662+ func rowAtIndexPath( _ indexPath: IndexPath ) -> Row {
663+ return sections [ indexPath. section] . rows [ indexPath. row]
664+ }
665+
666+ func note( at indexPath: IndexPath ) -> OrderNote ? {
667+ // We need to subtract 1 here because the first order note row is the "Add Order" cell
668+ let noteIndex = indexPath. row - 1
669+ guard orderNotes. indices. contains ( noteIndex) else {
670+ return nil
671+ }
672+
673+ return orderNotes [ noteIndex]
674+ }
675+
676+ /// Checks if copying the row data at the provided indexPath is allowed
677+ ///
678+ /// - Parameter indexPath: indexpath of the row to check
679+ /// - Returns: true is copying is allowed, false otherwise
680+ ///
681+ func checkIfCopyingIsAllowed( for indexPath: IndexPath ) -> Bool {
682+ let row = rowAtIndexPath ( indexPath)
683+ switch row {
684+ case . billingAddress:
685+ if let _ = viewModel. order. billingAddress {
686+ return true
687+ }
688+ case . shippingAddress:
689+ if let _ = viewModel. order. shippingAddress {
690+ return true
691+ }
692+ default :
693+ break
694+ }
695+
696+ return false
697+ }
698+
699+ /// Sends the provided Row's text data to the pasteboard
700+ ///
701+ /// - Parameter row: Row to copy text data from
702+ ///
703+ func copyText( at row: Row ) {
704+ switch row {
705+ case . billingAddress:
706+ sendToPasteboard ( viewModel. order. billingAddress? . fullNameWithCompanyAndAddress)
707+ case . shippingAddress:
708+ sendToPasteboard ( viewModel. order. shippingAddress? . fullNameWithCompanyAndAddress)
709+ default :
710+ break // We only send text to the pasteboard from the address rows right meow
711+ }
712+ }
713+
714+ /// Sends the provided text to the general pasteboard and triggers a success haptic. If the text param
715+ /// is nil, nothing is sent to the pasteboard.
716+ ///
717+ /// - Parameter text: string value to send to the pasteboard
718+ ///
719+ func sendToPasteboard( _ text: String ? ) {
720+ guard let text = text, text. isEmpty == false else {
721+ return
722+ }
723+
724+ // Insert an extra newline to make life easier when pasting
725+ UIPasteboard . general. string = text + " \n "
726+ hapticGenerator. notificationOccurred ( . success)
727+ }
728+ }
729+
730+
620731// MARK: - Contact Alert
621732//
622733private extension OrderDetailsViewController {
0 commit comments