Skip to content

Commit f52dff3

Browse files
authored
Merge pull request #10664 from woocommerce/issue-3885/variation-delete-confirmation
[Issue 3885] product variation delete confirmation dialog to a dialog fragment
2 parents f0914eb + 2b41899 commit f52dff3

File tree

6 files changed

+144
-13
lines changed

6 files changed

+144
-13
lines changed

RELEASE-NOTES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
17.3
88
-----
99
- [*] [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]
10+
- [*] [Internal] Enhanced product variation delete confirmation dialog visibility and functionality across device rotations [https://github.com/woocommerce/woocommerce-android/pull/10664]
1011
- [*] [Internal] Added a text along with the receipts file when it is shared [https://github.com/woocommerce/woocommerce-android/pull/10681]
1112

1213
17.2
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.woocommerce.android.ui.dialog
2+
3+
import android.os.Parcelable
4+
import androidx.annotation.StringRes
5+
import kotlinx.parcelize.Parcelize
6+
7+
@Parcelize
8+
data class DialogParams(
9+
@StringRes val titleId: Int? = null,
10+
@StringRes val messageId: Int? = null,
11+
@StringRes val positiveButtonId: Int? = null,
12+
@StringRes val negativeButtonId: Int? = null,
13+
@StringRes val neutralButtonId: Int? = null,
14+
val cancelable: Boolean = true
15+
) : Parcelable
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.woocommerce.android.ui.dialog
2+
3+
import android.app.Dialog
4+
import android.os.Bundle
5+
import androidx.fragment.app.DialogFragment
6+
import com.google.android.material.dialog.MaterialAlertDialogBuilder
7+
8+
class WooDialogFragment : DialogFragment() {
9+
10+
private var dialogInteractionListener: DialogInteractionListener? = null
11+
12+
fun setDialogInteractionListener(listener: DialogInteractionListener) {
13+
dialogInteractionListener = listener
14+
}
15+
16+
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
17+
@Suppress("DEPRECATION") val params = requireArguments().getParcelable<DialogParams>(ARG_DIALOG_PARAMS)!!
18+
19+
val builder = MaterialAlertDialogBuilder(requireContext())
20+
.setCancelable(params.cancelable)
21+
22+
params.titleId?.let { builder.setTitle(it) }
23+
params.messageId?.let { builder.setMessage(it) }
24+
params.positiveButtonId?.let { posId ->
25+
builder.setPositiveButton(posId) { _, _ ->
26+
dialogInteractionListener?.onPositiveButtonClicked()
27+
}
28+
}
29+
params.negativeButtonId?.let { negId ->
30+
builder.setNegativeButton(negId) { _, _ ->
31+
dialogInteractionListener?.onNegativeButtonClicked()
32+
}
33+
}
34+
params.neutralButtonId?.let { neutId ->
35+
builder.setNeutralButton(neutId) { _, _ ->
36+
dialogInteractionListener?.onNeutralButtonClicked()
37+
}
38+
}
39+
40+
return builder.create()
41+
}
42+
43+
interface DialogInteractionListener {
44+
fun onPositiveButtonClicked()
45+
fun onNegativeButtonClicked()
46+
fun onNeutralButtonClicked()
47+
}
48+
49+
companion object {
50+
const val ARG_DIALOG_PARAMS = "dialog_params"
51+
const val TAG = "WooDialogFragment"
52+
fun newInstance(params: DialogParams): WooDialogFragment {
53+
return WooDialogFragment().apply {
54+
arguments = Bundle().apply {
55+
putParcelable(ARG_DIALOG_PARAMS, params)
56+
}
57+
}
58+
}
59+
}
60+
}

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/variations/VariationDetailFragment.kt

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import com.woocommerce.android.model.VariantOption
3131
import com.woocommerce.android.ui.aztec.AztecEditorFragment
3232
import com.woocommerce.android.ui.base.BaseFragment
3333
import com.woocommerce.android.ui.base.UIMessageResolver
34+
import com.woocommerce.android.ui.dialog.WooDialogFragment
35+
import com.woocommerce.android.ui.dialog.WooDialogFragment.DialogInteractionListener
3436
import com.woocommerce.android.ui.main.MainActivity.Companion.BackPressListener
3537
import com.woocommerce.android.ui.products.BaseProductEditorFragment
3638
import com.woocommerce.android.ui.products.ProductInventoryViewModel.InventoryData
@@ -48,6 +50,7 @@ import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.Exit
4850
import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ExitWithResult
4951
import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ShowActionSnackbar
5052
import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ShowDialog
53+
import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ShowDialogFragment
5154
import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ShowSnackbar
5255
import com.woocommerce.android.widgets.CustomProgressDialog
5356
import com.woocommerce.android.widgets.SkeletonView
@@ -61,7 +64,8 @@ class VariationDetailFragment :
6164
BaseFragment(R.layout.fragment_variation_detail),
6265
BackPressListener,
6366
OnGalleryImageInteractionListener,
64-
MenuProvider {
67+
MenuProvider,
68+
DialogInteractionListener {
6569
companion object {
6670
private const val LIST_STATE_KEY = "list_state"
6771
const val KEY_VARIATION_DETAILS_RESULT = "key_variation_details_result"
@@ -95,11 +99,18 @@ class VariationDetailFragment :
9599

96100
_binding = FragmentVariationDetailBinding.bind(view)
97101

102+
reattachDialogInteractionListener()
103+
98104
requireActivity().addMenuProvider(this, viewLifecycleOwner)
99105
initializeViews(savedInstanceState)
100106
initializeViewModel()
101107
}
102108

109+
private fun reattachDialogInteractionListener() {
110+
val dialogFragment = parentFragmentManager.findFragmentByTag(WooDialogFragment.TAG) as? WooDialogFragment
111+
dialogFragment?.setDialogInteractionListener(this)
112+
}
113+
103114
override fun onDestroyView() {
104115
skeletonView.hide()
105116
imageUploadErrorsSnackbar?.dismiss()
@@ -276,12 +287,25 @@ class VariationDetailFragment :
276287

277288
is ExitWithResult<*> -> navigateBackWithResult(KEY_VARIATION_DETAILS_RESULT, event.data)
278289
is ShowDialog -> event.showDialog()
290+
is ShowDialogFragment -> event.showIn(parentFragmentManager, this)
279291
is Exit -> requireActivity().onBackPressedDispatcher.onBackPressed()
280292
else -> event.isHandled = false
281293
}
282294
}
283295
}
284296

297+
override fun onPositiveButtonClicked() {
298+
viewModel.onDeleteVariationConfirmed()
299+
}
300+
301+
override fun onNegativeButtonClicked() {
302+
viewModel.onDeleteVariationCancelled()
303+
}
304+
305+
override fun onNeutralButtonClicked() {
306+
// no-op
307+
}
308+
285309
private fun showVariationDetails(variation: ProductVariation) {
286310
if (variation.image == null && !viewModel.isUploadingImages()) {
287311
binding.imageGallery.hide()

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/variations/VariationDetailViewModel.kt

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -131,25 +131,27 @@ class VariationDetailViewModel @Inject constructor(
131131

132132
fun onDeleteVariationClicked() {
133133
triggerEvent(
134-
Event.ShowDialog(
135-
positiveBtnAction = { _, _ ->
136-
AnalyticsTracker.track(
137-
AnalyticsEvent.PRODUCT_VARIATION_REMOVE_BUTTON_TAPPED,
138-
mapOf(KEY_PRODUCT_ID to viewState.parentProduct?.remoteId)
139-
)
140-
viewState = viewState.copy(isConfirmingDeletion = false)
141-
deleteVariation()
142-
},
143-
negativeBtnAction = { _, _ ->
144-
viewState = viewState.copy(isConfirmingDeletion = false)
145-
},
134+
Event.ShowDialogFragment(
146135
messageId = string.variation_confirm_delete,
147136
positiveButtonId = string.delete,
148137
negativeButtonId = string.cancel
149138
)
150139
)
151140
}
152141

142+
fun onDeleteVariationConfirmed() {
143+
AnalyticsTracker.track(
144+
AnalyticsEvent.PRODUCT_VARIATION_REMOVE_BUTTON_TAPPED,
145+
mapOf(KEY_PRODUCT_ID to viewState.parentProduct?.remoteId)
146+
)
147+
viewState = viewState.copy(isConfirmingDeletion = false)
148+
deleteVariation()
149+
}
150+
151+
fun onDeleteVariationCancelled() {
152+
viewState = viewState.copy(isConfirmingDeletion = false)
153+
}
154+
153155
fun onExit() {
154156
when {
155157
isUploadingImages() -> {

WooCommerce/src/main/kotlin/com/woocommerce/android/viewmodel/MultiLiveEvent.kt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ import com.google.android.material.snackbar.Snackbar
1212
import com.woocommerce.android.R.string
1313
import com.woocommerce.android.model.UiString
1414
import com.woocommerce.android.support.help.HelpOrigin
15+
import com.woocommerce.android.ui.dialog.DialogParams
1516
import com.woocommerce.android.ui.dialog.WooDialog
17+
import com.woocommerce.android.ui.dialog.WooDialogFragment
1618
import com.woocommerce.android.viewmodel.MultiLiveEvent.Event
1719
import java.util.concurrent.atomic.AtomicBoolean
1820

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

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

134+
data class ShowDialogFragment(
135+
@StringRes val titleId: Int? = null,
136+
@StringRes val messageId: Int? = null,
137+
@StringRes val positiveButtonId: Int? = null,
138+
@StringRes val negativeButtonId: Int? = null,
139+
@StringRes val neutralButtonId: Int? = null,
140+
val cancelable: Boolean = true
141+
) : Event() {
142+
fun showIn(
143+
fragmentManager: androidx.fragment.app.FragmentManager,
144+
listener: WooDialogFragment.DialogInteractionListener
145+
) {
146+
val dialogParams = DialogParams(
147+
titleId = titleId,
148+
messageId = messageId,
149+
positiveButtonId = positiveButtonId,
150+
negativeButtonId = negativeButtonId,
151+
neutralButtonId = neutralButtonId,
152+
cancelable = cancelable
153+
)
154+
val dialogFragment = WooDialogFragment.newInstance(dialogParams).apply {
155+
setDialogInteractionListener(listener)
156+
}
157+
dialogFragment.show(fragmentManager, WooDialogFragment.TAG)
158+
}
159+
}
160+
132161
data class ShowDialog(
133162
@StringRes val titleId: Int? = null,
134163
@StringRes val messageId: Int? = null,

0 commit comments

Comments
 (0)