From 77559693f49c81599f7a15c43a4ad47502ac019d Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 31 Jan 2024 17:49:57 -0500 Subject: [PATCH 1/8] removed unused names for the actions. --- .../kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt index 6bc238d610b..88a8e23f765 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt @@ -137,9 +137,6 @@ open class MultiLiveEvent : MutableLiveData() { @StringRes val positiveButtonId: Int? = null, @StringRes val negativeButtonId: Int? = null, @StringRes val neutralButtonId: Int? = null, - val positiveActionName: String? = null, - val negativeActionName: String? = null, - val neutralActionName: String? = null, val cancelable: Boolean = true ) : Event() { fun showIn( From 65c419ed39277b91d3b729676788614984274584 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 31 Jan 2024 17:31:47 -0500 Subject: [PATCH 2/8] Created a dialog fragment that can survive config changes. --- .../android/ui/dialog/WooDialogFragment.kt | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dialog/WooDialogFragment.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dialog/WooDialogFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dialog/WooDialogFragment.kt new file mode 100644 index 00000000000..83dd8d2c247 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dialog/WooDialogFragment.kt @@ -0,0 +1,60 @@ +package com.woocommerce.android.ui.dialog + +import android.app.Dialog +import android.os.Bundle +import androidx.fragment.app.DialogFragment +import com.google.android.material.dialog.MaterialAlertDialogBuilder + +class WooDialogFragment : DialogFragment() { + + private var dialogInteractionListener: DialogInteractionListener? = null + + fun setDialogInteractionListener(listener: DialogInteractionListener) { + dialogInteractionListener = listener + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + @Suppress("DEPRECATION") val params = requireArguments().getParcelable(ARG_DIALOG_PARAMS)!! + + val builder = MaterialAlertDialogBuilder(requireContext()) + .setCancelable(params.cancelable) + + params.titleId?.let { builder.setTitle(it) } + params.messageId?.let { builder.setMessage(it) } + params.positiveButtonId?.let { posId -> + builder.setPositiveButton(posId) { _, _ -> + dialogInteractionListener?.onPositiveButtonClicked() + } + } + params.negativeButtonId?.let { negId -> + builder.setNegativeButton(negId) { _, _ -> + dialogInteractionListener?.onNegativeButtonClicked() + } + } + params.neutralButtonId?.let { neutId -> + builder.setNeutralButton(neutId) { _, _ -> + dialogInteractionListener?.onNeutralButtonClicked() + } + } + + return builder.create() + } + + interface DialogInteractionListener { + fun onPositiveButtonClicked() + fun onNegativeButtonClicked() + fun onNeutralButtonClicked() + } + + companion object { + const val ARG_DIALOG_PARAMS = "dialog_params" + const val TAG = "WooDialogFragment" + fun newInstance(params: DialogParams): WooDialogFragment { + return WooDialogFragment().apply { + arguments = Bundle().apply { + putParcelable(ARG_DIALOG_PARAMS, params) + } + } + } + } +} From 917fff74cd15ae73cf7027cb966cb44f5df6c15f Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 1 Feb 2024 02:19:15 -0500 Subject: [PATCH 3/8] Added it to the MultiLiveEvent --- .../woocommerce/android/viewmodel/MultiLiveEvent.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt index a921030edae..8622d77c3de 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt @@ -12,7 +12,9 @@ import com.google.android.material.snackbar.Snackbar import com.woocommerce.android.R.string import com.woocommerce.android.model.UiString import com.woocommerce.android.support.help.HelpOrigin +import com.woocommerce.android.ui.dialog.DialogParams import com.woocommerce.android.ui.dialog.WooDialog +import com.woocommerce.android.ui.dialog.WooDialogFragment import com.woocommerce.android.viewmodel.MultiLiveEvent.Event import java.util.concurrent.atomic.AtomicBoolean @@ -135,12 +137,12 @@ open class MultiLiveEvent : MutableLiveData() { @StringRes val positiveButtonId: Int? = null, @StringRes val negativeButtonId: Int? = null, @StringRes val neutralButtonId: Int? = null, + val positiveActionName: String? = null, + val negativeActionName: String? = null, + val neutralActionName: String? = null, val cancelable: Boolean = true ) : Event() { - fun showIn( - fragmentManager: androidx.fragment.app.FragmentManager, - listener: WooDialogFragment.DialogInteractionListener - ) { + fun showIn(fragmentManager: androidx.fragment.app.FragmentManager, listener: WooDialogFragment.DialogInteractionListener) { val dialogParams = DialogParams( titleId = titleId, messageId = messageId, From 03f6be070f37ab23a6f37827c130d795e0a4dc52 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 31 Jan 2024 17:32:20 -0500 Subject: [PATCH 4/8] Created dialog params for the dialog fragment --- .../woocommerce/android/ui/dialog/DialogParams.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dialog/DialogParams.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dialog/DialogParams.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dialog/DialogParams.kt new file mode 100644 index 00000000000..e484ec323b0 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dialog/DialogParams.kt @@ -0,0 +1,15 @@ +package com.woocommerce.android.ui.dialog + +import android.os.Parcelable +import androidx.annotation.StringRes +import kotlinx.parcelize.Parcelize + +@Parcelize +data class DialogParams( + @StringRes val titleId: Int? = null, + @StringRes val messageId: Int? = null, + @StringRes val positiveButtonId: Int? = null, + @StringRes val negativeButtonId: Int? = null, + @StringRes val neutralButtonId: Int? = null, + val cancelable: Boolean = true +) : Parcelable From 3cb1f50195e0000a4eecdf5e13e7a754b404c7d2 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 31 Jan 2024 17:40:09 -0500 Subject: [PATCH 5/8] Fixed detekt error. --- .../com/woocommerce/android/viewmodel/MultiLiveEvent.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt index 8622d77c3de..6bc238d610b 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt @@ -142,7 +142,10 @@ open class MultiLiveEvent : MutableLiveData() { val neutralActionName: String? = null, val cancelable: Boolean = true ) : Event() { - fun showIn(fragmentManager: androidx.fragment.app.FragmentManager, listener: WooDialogFragment.DialogInteractionListener) { + fun showIn( + fragmentManager: androidx.fragment.app.FragmentManager, + listener: WooDialogFragment.DialogInteractionListener + ) { val dialogParams = DialogParams( titleId = titleId, messageId = messageId, From 787dd807c322998cfa24f21a83d365f93a381a2a Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 31 Jan 2024 17:40:29 -0500 Subject: [PATCH 6/8] Implemented the show dialog fragment for variations. --- .../variations/VariationDetailFragment.kt | 26 ++++++++++++++++++- .../variations/VariationDetailViewModel.kt | 26 ++++++++++--------- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/variations/VariationDetailFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/variations/VariationDetailFragment.kt index 20f3f4a9d24..ccf61aacef7 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/variations/VariationDetailFragment.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/variations/VariationDetailFragment.kt @@ -31,6 +31,8 @@ import com.woocommerce.android.model.VariantOption import com.woocommerce.android.ui.aztec.AztecEditorFragment import com.woocommerce.android.ui.base.BaseFragment import com.woocommerce.android.ui.base.UIMessageResolver +import com.woocommerce.android.ui.dialog.WooDialogFragment +import com.woocommerce.android.ui.dialog.WooDialogFragment.DialogInteractionListener import com.woocommerce.android.ui.main.MainActivity.Companion.BackPressListener import com.woocommerce.android.ui.products.BaseProductEditorFragment import com.woocommerce.android.ui.products.ProductInventoryViewModel.InventoryData @@ -48,6 +50,7 @@ import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.Exit import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ExitWithResult import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ShowActionSnackbar import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ShowDialog +import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ShowDialogFragment import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ShowSnackbar import com.woocommerce.android.widgets.CustomProgressDialog import com.woocommerce.android.widgets.SkeletonView @@ -61,7 +64,8 @@ class VariationDetailFragment : BaseFragment(R.layout.fragment_variation_detail), BackPressListener, OnGalleryImageInteractionListener, - MenuProvider { + MenuProvider, + DialogInteractionListener { companion object { private const val LIST_STATE_KEY = "list_state" const val KEY_VARIATION_DETAILS_RESULT = "key_variation_details_result" @@ -95,11 +99,18 @@ class VariationDetailFragment : _binding = FragmentVariationDetailBinding.bind(view) + reattachDialogInteractionListener() + requireActivity().addMenuProvider(this, viewLifecycleOwner) initializeViews(savedInstanceState) initializeViewModel() } + private fun reattachDialogInteractionListener() { + val dialogFragment = parentFragmentManager.findFragmentByTag(WooDialogFragment.TAG) as? WooDialogFragment + dialogFragment?.setDialogInteractionListener(this) + } + override fun onDestroyView() { skeletonView.hide() imageUploadErrorsSnackbar?.dismiss() @@ -276,12 +287,25 @@ class VariationDetailFragment : is ExitWithResult<*> -> navigateBackWithResult(KEY_VARIATION_DETAILS_RESULT, event.data) is ShowDialog -> event.showDialog() + is ShowDialogFragment -> event.showIn(parentFragmentManager, this) is Exit -> requireActivity().onBackPressedDispatcher.onBackPressed() else -> event.isHandled = false } } } + override fun onPositiveButtonClicked() { + viewModel.onDeleteVariationConfirmed() + } + + override fun onNegativeButtonClicked() { + viewModel.onDeleteVariationCancelled() + } + + override fun onNeutralButtonClicked() { + // no-op + } + private fun showVariationDetails(variation: ProductVariation) { if (variation.image == null && !viewModel.isUploadingImages()) { binding.imageGallery.hide() diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/variations/VariationDetailViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/variations/VariationDetailViewModel.kt index f3d5941718f..8b502da15bd 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/variations/VariationDetailViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/variations/VariationDetailViewModel.kt @@ -131,18 +131,7 @@ class VariationDetailViewModel @Inject constructor( fun onDeleteVariationClicked() { triggerEvent( - Event.ShowDialog( - positiveBtnAction = { _, _ -> - AnalyticsTracker.track( - AnalyticsEvent.PRODUCT_VARIATION_REMOVE_BUTTON_TAPPED, - mapOf(KEY_PRODUCT_ID to viewState.parentProduct?.remoteId) - ) - viewState = viewState.copy(isConfirmingDeletion = false) - deleteVariation() - }, - negativeBtnAction = { _, _ -> - viewState = viewState.copy(isConfirmingDeletion = false) - }, + Event.ShowDialogFragment( messageId = string.variation_confirm_delete, positiveButtonId = string.delete, negativeButtonId = string.cancel @@ -150,6 +139,19 @@ class VariationDetailViewModel @Inject constructor( ) } + fun onDeleteVariationConfirmed() { + AnalyticsTracker.track( + AnalyticsEvent.PRODUCT_VARIATION_REMOVE_BUTTON_TAPPED, + mapOf(KEY_PRODUCT_ID to viewState.parentProduct?.remoteId) + ) + viewState = viewState.copy(isConfirmingDeletion = false) + deleteVariation() + } + + fun onDeleteVariationCancelled() { + viewState = viewState.copy(isConfirmingDeletion = false) + } + fun onExit() { when { isUploadingImages() -> { From 3069927b77e341fe299c7e9820c3f7e6588932a8 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 31 Jan 2024 17:49:57 -0500 Subject: [PATCH 7/8] removed unused names for the actions. --- .../kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt index 6bc238d610b..88a8e23f765 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt @@ -137,9 +137,6 @@ open class MultiLiveEvent : MutableLiveData() { @StringRes val positiveButtonId: Int? = null, @StringRes val negativeButtonId: Int? = null, @StringRes val neutralButtonId: Int? = null, - val positiveActionName: String? = null, - val negativeActionName: String? = null, - val neutralActionName: String? = null, val cancelable: Boolean = true ) : Event() { fun showIn( From 18094aa19b8f83228374d9a14e1a4d2de31353cb Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Fri, 2 Feb 2024 11:18:53 -0500 Subject: [PATCH 8/8] Added release notes. --- RELEASE-NOTES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 52bbdb01e52..60e39c27fc1 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -3,6 +3,8 @@ 17.3 ----- - [*] [Internal] Enhanced user experience in shipping label creation with automatic scrolling to the first invalid field upon form submission failure [https://github.com/woocommerce/woocommerce-android/pull/10657] +- [*] [Internal] Enhanced product variation delete confirmation dialog visibility and functionality across device rotations [https://github.com/woocommerce/woocommerce-android/pull/10664] + 17.2 ----- - [**] [Available for users with WooCommerce version of 8.7+, which is not released yet] Every order have a receipt now. The receipts can be shared via many apps installed on the phone [https://github.com/woocommerce/woocommerce-android/pull/10650]