From 5943e283290cb486920b22076b729a749f530964 Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Mon, 22 May 2023 14:47:07 +0800 Subject: [PATCH 1/4] Show share CTA in product form navigation bar if the product is shareable and only up to one action is visible. --- .../Edit Product/ProductFormViewController.swift | 13 +++++++++++++ .../Edit Product/ProductFormViewModel.swift | 5 +++++ .../Edit Product/ProductFormViewModelProtocol.swift | 1 + 3 files changed, 19 insertions(+) diff --git a/WooCommerce/Classes/ViewRelated/Products/Edit Product/ProductFormViewController.swift b/WooCommerce/Classes/ViewRelated/Products/Edit Product/ProductFormViewController.swift index 1d9ef0755f8..1f53fbca2e4 100644 --- a/WooCommerce/Classes/ViewRelated/Products/Edit Product/ProductFormViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Products/Edit Product/ProductFormViewController.swift @@ -470,6 +470,11 @@ final class ProductFormViewController: } } + @objc private func shareProduct() { + ServiceLocator.analytics.track(.productDetailShareButtonTapped) + displayShareProduct() + } + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { let section = tableViewModel.sections[section] switch section { @@ -1003,6 +1008,8 @@ private extension ProductFormViewController { return createSaveBarButtonItem() case .more: return createMoreOptionsBarButtonItem() + case .share: + return createShareBarButtonItem() } } @@ -1048,6 +1055,12 @@ private extension ProductFormViewController { moreButton.accessibilityIdentifier = "edit-product-more-options-button" return moreButton } + + func createShareBarButtonItem() -> UIBarButtonItem { + UIBarButtonItem(barButtonSystemItem: .action, + target: self, + action: #selector(shareProduct)) + } } // MARK: - Keyboard management diff --git a/WooCommerce/Classes/ViewRelated/Products/Edit Product/ProductFormViewModel.swift b/WooCommerce/Classes/ViewRelated/Products/Edit Product/ProductFormViewModel.swift index 0816a4732b6..47d2a430be2 100644 --- a/WooCommerce/Classes/ViewRelated/Products/Edit Product/ProductFormViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Products/Edit Product/ProductFormViewModel.swift @@ -168,6 +168,11 @@ final class ProductFormViewModel: ProductFormViewModelProtocol { buttons.append(.more) } + // Share button if up to one button is visible. + if canShareProduct() && buttons.count <= 1 { + buttons.insert(.share, at: 0) + } + return buttons } diff --git a/WooCommerce/Classes/ViewRelated/Products/Edit Product/ProductFormViewModelProtocol.swift b/WooCommerce/Classes/ViewRelated/Products/Edit Product/ProductFormViewModelProtocol.swift index 13dc19b0b48..0fd14f3cf7a 100644 --- a/WooCommerce/Classes/ViewRelated/Products/Edit Product/ProductFormViewModelProtocol.swift +++ b/WooCommerce/Classes/ViewRelated/Products/Edit Product/ProductFormViewModelProtocol.swift @@ -14,6 +14,7 @@ enum ActionButtonType { case publish case save case more + case share } /// The type of save message when saving a product. From aa0083d2a9208580583e5457f854b98dafe0335c Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Mon, 22 May 2023 15:16:57 +0800 Subject: [PATCH 2/4] Add an event property `source` to track the source of share product action. --- .../WooAnalyticsEvent+ProductForm.swift | 24 +++++++++++++++++++ .../ProductFormViewController.swift | 10 ++++---- .../WooCommerce.xcodeproj/project.pbxproj | 4 ++++ 3 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 WooCommerce/Classes/Analytics/WooAnalyticsEvent+ProductForm.swift diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsEvent+ProductForm.swift b/WooCommerce/Classes/Analytics/WooAnalyticsEvent+ProductForm.swift new file mode 100644 index 00000000000..d68ff16bfba --- /dev/null +++ b/WooCommerce/Classes/Analytics/WooAnalyticsEvent+ProductForm.swift @@ -0,0 +1,24 @@ +extension WooAnalyticsEvent { + enum ProductForm { + /// Event property keys. + private enum Key { + static let source = "source" + } + + /// Tracked when the user taps on the button to share a product. + static func productDetailShareButtonTapped(source: ShareProductSource) -> WooAnalyticsEvent { + WooAnalyticsEvent(statName: .productDetailShareButtonTapped, + properties: [Key.source: source.rawValue]) + } + } +} + +extension WooAnalyticsEvent.ProductForm { + /// Source of the share product action. The raw value is the event property value. + enum ShareProductSource: String { + /// From product form in the navigation bar. + case productForm = "product_form" + /// From product form > more menu in the navigation bar. + case moreMenu = "more_menu" + } +} diff --git a/WooCommerce/Classes/ViewRelated/Products/Edit Product/ProductFormViewController.swift b/WooCommerce/Classes/ViewRelated/Products/Edit Product/ProductFormViewController.swift index 1f53fbca2e4..45077398198 100644 --- a/WooCommerce/Classes/ViewRelated/Products/Edit Product/ProductFormViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Products/Edit Product/ProductFormViewController.swift @@ -281,8 +281,7 @@ final class ProductFormViewController: if viewModel.canShareProduct() { actionSheet.addDefaultActionWithTitle(ActionSheetStrings.share) { [weak self] _ in - ServiceLocator.analytics.track(.productDetailShareButtonTapped) - self?.displayShareProduct() + self?.displayShareProduct(source: .moreMenu) } } @@ -471,8 +470,7 @@ final class ProductFormViewController: } @objc private func shareProduct() { - ServiceLocator.analytics.track(.productDetailShareButtonTapped) - displayShareProduct() + displayShareProduct(source: .productForm) } func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { @@ -863,7 +861,9 @@ private extension ProductFormViewController { WebviewHelper.launch(url, with: self) } - func displayShareProduct() { + func displayShareProduct(source: WooAnalyticsEvent.ProductForm.ShareProductSource) { + ServiceLocator.analytics.track(event: .ProductForm.productDetailShareButtonTapped(source: source)) + guard let url = URL(string: product.permalink) else { return } diff --git a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj index c5045088841..3d1e4e58ec8 100644 --- a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj +++ b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj @@ -191,6 +191,7 @@ 02490D1E284F3226002096EF /* ProductImagesSaverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02490D1D284F3226002096EF /* ProductImagesSaverTests.swift */; }; 024A543422BA6F8F00F4F38E /* DeveloperEmailChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 024A543322BA6F8F00F4F38E /* DeveloperEmailChecker.swift */; }; 024A543622BA84DB00F4F38E /* DeveloperEmailCheckerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 024A543522BA84DB00F4F38E /* DeveloperEmailCheckerTests.swift */; }; + 024D4E842A1B4B630090E0E6 /* WooAnalyticsEvent+ProductForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 024D4E832A1B4B630090E0E6 /* WooAnalyticsEvent+ProductForm.swift */; }; 024DF3052372ADCD006658FE /* KeyboardScrollable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 024DF3042372ADCD006658FE /* KeyboardScrollable.swift */; }; 024DF3072372C18D006658FE /* AztecUIConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 024DF3062372C18D006658FE /* AztecUIConfigurator.swift */; }; 024DF3092372CA00006658FE /* EditorViewProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 024DF3082372CA00006658FE /* EditorViewProperties.swift */; }; @@ -2481,6 +2482,7 @@ 02490D1D284F3226002096EF /* ProductImagesSaverTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductImagesSaverTests.swift; sourceTree = ""; }; 024A543322BA6F8F00F4F38E /* DeveloperEmailChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperEmailChecker.swift; sourceTree = ""; }; 024A543522BA84DB00F4F38E /* DeveloperEmailCheckerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperEmailCheckerTests.swift; sourceTree = ""; }; + 024D4E832A1B4B630090E0E6 /* WooAnalyticsEvent+ProductForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WooAnalyticsEvent+ProductForm.swift"; sourceTree = ""; }; 024DF3042372ADCD006658FE /* KeyboardScrollable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardScrollable.swift; sourceTree = ""; }; 024DF3062372C18D006658FE /* AztecUIConfigurator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AztecUIConfigurator.swift; sourceTree = ""; }; 024DF3082372CA00006658FE /* EditorViewProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorViewProperties.swift; sourceTree = ""; }; @@ -7451,6 +7453,7 @@ 02B21C5629C9EEF900C5623B /* WooAnalyticsEvent+StoreOnboarding.swift */, DE621F6929D67E1B000DE3BD /* WooAnalyticsEvent+JetpackSetup.swift */, 02E222C729FBA60F004579A1 /* WooAnalyticsEvent+ProductFormAI.swift */, + 024D4E832A1B4B630090E0E6 /* WooAnalyticsEvent+ProductForm.swift */, ); path = Analytics; sourceTree = ""; @@ -11178,6 +11181,7 @@ 03BB9EA5292E2D0C00251E9E /* CardReaderConnectionController.swift in Sources */, B95112DA28BF79CA00D9578D /* PaymentsRoute.swift in Sources */, 7E6A019F2725CD76001668D5 /* FilterProductCategoryListViewModel.swift in Sources */, + 024D4E842A1B4B630090E0E6 /* WooAnalyticsEvent+ProductForm.swift in Sources */, CC53FB3C2757EC7200C4CA4F /* ProductSelectorViewModel.swift in Sources */, CCA1D5FE293F537400B40560 /* DeltaPercentage.swift in Sources */, 4569D3C325DC008700CDC3E2 /* SiteAddress.swift in Sources */, From 6d113c1fc6c6d8ff1cf9bce632f20f56aef936bf Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Mon, 22 May 2023 15:17:10 +0800 Subject: [PATCH 3/4] Update unit tests on the product form actions. --- .../Products/Edit Product/ProductFormViewModelTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WooCommerce/WooCommerceTests/ViewRelated/Products/Edit Product/ProductFormViewModelTests.swift b/WooCommerce/WooCommerceTests/ViewRelated/Products/Edit Product/ProductFormViewModelTests.swift index 6523d014bae..34e1ecd6b8f 100644 --- a/WooCommerce/WooCommerceTests/ViewRelated/Products/Edit Product/ProductFormViewModelTests.swift +++ b/WooCommerce/WooCommerceTests/ViewRelated/Products/Edit Product/ProductFormViewModelTests.swift @@ -357,7 +357,7 @@ final class ProductFormViewModelTests: XCTestCase { let actionButtons = viewModel.actionButtons // Then - XCTAssertEqual(actionButtons, [.more]) + XCTAssertEqual(actionButtons, [.share, .more]) } func test_action_buttons_for_existing_draft_product_and_pending_changes() { @@ -425,7 +425,7 @@ final class ProductFormViewModelTests: XCTestCase { let actionButtons = viewModel.actionButtons // Then - XCTAssertEqual(actionButtons, [.more]) + XCTAssertEqual(actionButtons, [.share, .more]) } func test_no_preview_button_for_existing_draft_product_on_site_with_no_frame_nonce() { From 77ed9a3bb7f95979006434aef779a3fd851d1904 Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Mon, 22 May 2023 15:36:26 +0800 Subject: [PATCH 4/4] Update release notes. --- RELEASE-NOTES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index bb5b5f87a90..a3a6626ab7e 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -2,7 +2,7 @@ 13.8 ----- - +- [*] Product form: a share action is shown in the navigation bar if the product can be shared and no more than one action is displayed, in addition to the more menu > Share. [https://github.com/woocommerce/woocommerce-ios/pull/9789] 13.7 -----