Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Issue 3885] product variation delete confirmation dialog to a dialog fragment #10664

Merged
merged 11 commits into from
Feb 8, 2024
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
Loading