From b4e6119c80b6d9c3e2b885528a59fa7410cf7104 Mon Sep 17 00:00:00 2001 From: Hafiz Rahman Date: Mon, 22 May 2023 19:31:37 +0700 Subject: [PATCH 1/5] Add: Show "Share" CTA next to ellipsis menu if Save/Publish option is not shown there. --- .../android/ui/products/ProductDetailFragment.kt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailFragment.kt index 484f92ea509b..5aae104e0a77 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailFragment.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailFragment.kt @@ -556,7 +556,18 @@ class ProductDetailFragment : setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM) } } - findItem(R.id.menu_share)?.isVisible = state.shareOption + findItem(R.id.menu_share)?.apply { + isVisible = state.shareOption + + // Show as action with text if "Save" or "Publish" is not currently shown as action with text. + setShowAsActionFlags( + if (isVisible && !state.saveOption && !state.publishOption) { + MenuItem.SHOW_AS_ACTION_IF_ROOM + } else { + MenuItem.SHOW_AS_ACTION_NEVER + } + ) + } findItem(R.id.menu_trash_product)?.isVisible = state.trashOption } From d7e3444fa9a14144d54ab70eedc1ed02caa1000f Mon Sep 17 00:00:00 2001 From: Hafiz Rahman Date: Mon, 22 May 2023 20:05:28 +0700 Subject: [PATCH 2/5] Refactor: Moving "Share" CTA showing logic to view model instead. --- .../android/ui/products/ProductDetailFragment.kt | 3 +-- .../android/ui/products/ProductDetailViewModel.kt | 13 +++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailFragment.kt index 5aae104e0a77..4b57cb5256e5 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailFragment.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailFragment.kt @@ -559,9 +559,8 @@ class ProductDetailFragment : findItem(R.id.menu_share)?.apply { isVisible = state.shareOption - // Show as action with text if "Save" or "Publish" is not currently shown as action with text. setShowAsActionFlags( - if (isVisible && !state.saveOption && !state.publishOption) { + if (state.showShareOptionAsActionWithText) { MenuItem.SHOW_AS_ACTION_IF_ROOM } else { MenuItem.SHOW_AS_ACTION_NEVER diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailViewModel.kt index 949d187db86c..1955840e1ce2 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailViewModel.kt @@ -255,12 +255,20 @@ class ProductDetailViewModel @Inject constructor( val showSaveOptionAsActionWithText = hasChanges && (isNotPublishedUnderCreation || !isProductUnderCreation) val isProductPublished = productDraft.status == ProductStatus.PUBLISH val isProductPublishedOrPrivate = isProductPublished || productDraft.status == ProductStatus.PRIVATE + val showPublishOption = !isProductPublishedOrPrivate || isProductUnderCreation + val showShareOption = !isProductUnderCreation + + // Show as action with text if "Save" or "Publish" is not currently shown as action with text. + val showShareOptionAsActionWithText = + showShareOption && !showSaveOptionAsActionWithText && !showPublishOption + MenuButtonsState( saveOption = showSaveOptionAsActionWithText, saveAsDraftOption = canBeSavedAsDraft, - publishOption = !isProductPublishedOrPrivate || isProductUnderCreation, + publishOption = showPublishOption, viewProductOption = isProductPublished && !isProductUnderCreation, - shareOption = !isProductUnderCreation, + shareOption = showShareOption, + showShareOptionAsActionWithText = showShareOptionAsActionWithText, trashOption = !isProductUnderCreation && navArgs.isTrashEnabled ) }.asLiveData() @@ -2339,6 +2347,7 @@ class ProductDetailViewModel @Inject constructor( val publishOption: Boolean, val viewProductOption: Boolean, val shareOption: Boolean, + val showShareOptionAsActionWithText: Boolean, val trashOption: Boolean ) } From 034f7e3c48d4332a514097e4f062d5ef9f724ffd Mon Sep 17 00:00:00 2001 From: Hafiz Rahman Date: Mon, 22 May 2023 20:32:31 +0700 Subject: [PATCH 3/5] Add: Analytics for share button click based on sources. --- .../android/analytics/AnalyticsTracker.kt | 4 ++++ .../ui/products/ProductDetailViewModel.kt | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/analytics/AnalyticsTracker.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/analytics/AnalyticsTracker.kt index a1813f0355c6..65a534c21f2f 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/analytics/AnalyticsTracker.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/analytics/AnalyticsTracker.kt @@ -366,6 +366,10 @@ class AnalyticsTracker private constructor(private val context: Context) { private const val PREFKEY_SEND_USAGE_STATS = "wc_pref_send_usage_stats" + // -- Product details + const val VALUE_SHARE_BUTTON_SOURCE_PRODUCT_FORM = "product_form" + const val VALUE_SHARE_BUTTON_SOURCE_MORE_MENU = "more_menu" + // -- Product Variations const val KEY_VARIATIONS_COUNT = "variations_count" diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailViewModel.kt index 1955840e1ce2..d7e1d7b12deb 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailViewModel.kt @@ -241,6 +241,8 @@ class ProductDetailViewModel @Inject constructor( val productDraftAttributes get() = viewState.productDraft?.attributes ?: emptyList() + private var isShareButtonShownAsActionWithText = false + val menuButtonsState = draftChanges .filterNotNull() .combine(_hasChanges) { productDraft, hasChanges -> @@ -262,6 +264,8 @@ class ProductDetailViewModel @Inject constructor( val showShareOptionAsActionWithText = showShareOption && !showSaveOptionAsActionWithText && !showPublishOption + isShareButtonShownAsActionWithText = showShareOptionAsActionWithText + MenuButtonsState( saveOption = showSaveOptionAsActionWithText, saveAsDraftOption = canBeSavedAsDraft, @@ -370,7 +374,19 @@ class ProductDetailViewModel @Inject constructor( * Called when the Share menu button is clicked in Product detail screen */ fun onShareButtonClicked() { - tracker.track(AnalyticsEvent.PRODUCT_DETAIL_SHARE_BUTTON_TAPPED) + val source = if (isShareButtonShownAsActionWithText) { + AnalyticsTracker.VALUE_SHARE_BUTTON_SOURCE_PRODUCT_FORM + } else { + AnalyticsTracker.VALUE_SHARE_BUTTON_SOURCE_MORE_MENU + } + + tracker.track( + AnalyticsEvent.PRODUCT_DETAIL_SHARE_BUTTON_TAPPED, + mapOf( + AnalyticsTracker.KEY_SOURCE to source + ) + ) + viewState.productDraft?.let { triggerEvent(ProductNavigationTarget.ShareProduct(it.permalink, it.name)) } From c8fee8ddc7a2b35b3d318f08ef08ed5b76cab39e Mon Sep 17 00:00:00 2001 From: Hafiz Rahman Date: Mon, 22 May 2023 20:33:56 +0700 Subject: [PATCH 4/5] Delete unused import. --- .../woocommerce/android/ui/products/ProductDetailViewModel.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailViewModel.kt index d7e1d7b12deb..4314c9e6c5c2 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailViewModel.kt @@ -89,7 +89,6 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterNotNull -import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onCompletion From 84ddbaff620affce575c91aaa798b5b24b7ce7a2 Mon Sep 17 00:00:00 2001 From: Hafiz Rahman Date: Tue, 23 May 2023 14:28:27 +0700 Subject: [PATCH 5/5] Simplify logic for checking if share button is shown as action with text. --- .../ui/products/ProductDetailViewModel.kt | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailViewModel.kt index 4314c9e6c5c2..c7522de1c890 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/ProductDetailViewModel.kt @@ -240,8 +240,6 @@ class ProductDetailViewModel @Inject constructor( val productDraftAttributes get() = viewState.productDraft?.attributes ?: emptyList() - private var isShareButtonShownAsActionWithText = false - val menuButtonsState = draftChanges .filterNotNull() .combine(_hasChanges) { productDraft, hasChanges -> @@ -263,8 +261,6 @@ class ProductDetailViewModel @Inject constructor( val showShareOptionAsActionWithText = showShareOption && !showSaveOptionAsActionWithText && !showPublishOption - isShareButtonShownAsActionWithText = showShareOptionAsActionWithText - MenuButtonsState( saveOption = showSaveOptionAsActionWithText, saveAsDraftOption = canBeSavedAsDraft, @@ -373,21 +369,23 @@ class ProductDetailViewModel @Inject constructor( * Called when the Share menu button is clicked in Product detail screen */ fun onShareButtonClicked() { - val source = if (isShareButtonShownAsActionWithText) { - AnalyticsTracker.VALUE_SHARE_BUTTON_SOURCE_PRODUCT_FORM - } else { - AnalyticsTracker.VALUE_SHARE_BUTTON_SOURCE_MORE_MENU - } + menuButtonsState.value?.showShareOptionAsActionWithText?.let { isShownAsActionWithText -> + val source = if (isShownAsActionWithText) { + AnalyticsTracker.VALUE_SHARE_BUTTON_SOURCE_PRODUCT_FORM + } else { + AnalyticsTracker.VALUE_SHARE_BUTTON_SOURCE_MORE_MENU + } - tracker.track( - AnalyticsEvent.PRODUCT_DETAIL_SHARE_BUTTON_TAPPED, - mapOf( - AnalyticsTracker.KEY_SOURCE to source + tracker.track( + AnalyticsEvent.PRODUCT_DETAIL_SHARE_BUTTON_TAPPED, + mapOf( + AnalyticsTracker.KEY_SOURCE to source + ) ) - ) - viewState.productDraft?.let { - triggerEvent(ProductNavigationTarget.ShareProduct(it.permalink, it.name)) + viewState.productDraft?.let { + triggerEvent(ProductNavigationTarget.ShareProduct(it.permalink, it.name)) + } } }