Skip to content

Commit

Permalink
Merge pull request #10664 from woocommerce/issue-3885/variation-delet…
Browse files Browse the repository at this point in the history
…e-confirmation

[Issue 3885] product variation delete confirmation dialog to a dialog fragment
  • Loading branch information
jd-alexander authored Feb 8, 2024
2 parents f0914eb + 2b41899 commit f52dff3
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 13 deletions.
1 change: 1 addition & 0 deletions RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
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]
- [*] [Internal] Added a text along with the receipts file when it is shared [https://github.com/woocommerce/woocommerce-android/pull/10681]

17.2
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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<DialogParams>(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)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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"
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,25 +131,27 @@ 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
)
)
}

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() -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -129,6 +131,33 @@ open class MultiLiveEvent<T : Event> : MutableLiveData<T>() {

data class LaunchUrlInChromeTab(val url: String) : Event()

data class ShowDialogFragment(
@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
) : Event() {
fun showIn(
fragmentManager: androidx.fragment.app.FragmentManager,
listener: WooDialogFragment.DialogInteractionListener
) {
val dialogParams = DialogParams(
titleId = titleId,
messageId = messageId,
positiveButtonId = positiveButtonId,
negativeButtonId = negativeButtonId,
neutralButtonId = neutralButtonId,
cancelable = cancelable
)
val dialogFragment = WooDialogFragment.newInstance(dialogParams).apply {
setDialogInteractionListener(listener)
}
dialogFragment.show(fragmentManager, WooDialogFragment.TAG)
}
}

data class ShowDialog(
@StringRes val titleId: Int? = null,
@StringRes val messageId: Int? = null,
Expand Down

0 comments on commit f52dff3

Please sign in to comment.