Skip to content

Commit

Permalink
Merge pull request #13227 from woocommerce/task/bulk-order-config-change
Browse files Browse the repository at this point in the history
[Bulk Update Orders] Persist selection on configuration change and load more
  • Loading branch information
hafizrahman authored Jan 3, 2025
2 parents 22e1f7f + 5639575 commit 37c5583
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,3 @@ class DefaultOrderItemDetailsLookup(
override fun getPosition() = position
override fun getSelectionKey() = orderId
}

class SelectableOrderItemDetailsLookup(
private val position: Int,
private val orderId: Long
) : ItemDetailsLookup.ItemDetails<Long>() {
override fun getPosition() = position
override fun getSelectionKey() = orderId
override fun inSelectionHotspot(e: MotionEvent) = true
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ class OrderSelectionItemKeyProvider(private val recyclerView: RecyclerView) :
}
}

override fun getPosition(key: Long): Int {
return (recyclerView.adapter as? OrderListAdapter)?.currentList
?.indexOfFirst { item ->
item is OrderListItemUIType.OrderListItemUI && item.orderId == key
} ?: RecyclerView.NO_POSITION
}
override fun getPosition(key: Long): Int =
(recyclerView.adapter as? OrderListAdapter)?.orderIdAndPosition[key] ?: RecyclerView.NO_POSITION
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.woocommerce.android.ui.orders.list.OrderListItemUIType.SectionHeader
import com.woocommerce.android.util.CurrencyFormatter
import com.woocommerce.android.widgets.tags.TagView
import org.wordpress.android.fluxc.model.WCOrderStatusModel

class OrderListAdapter(
val listener: OrderListListener,
val currencyFormatter: CurrencyFormatter
Expand All @@ -38,6 +39,7 @@ class OrderListAdapter(
var activeOrderStatusMap: Map<String, WCOrderStatusModel> = emptyMap()
var allOrderIds: List<Long> = listOf()
var tracker: SelectionTracker<Long>? = null
var orderIdAndPosition = mutableMapOf<Long, Int>()

override fun getItemViewType(position: Int): Int {
return when (getItem(position)) {
Expand All @@ -61,10 +63,12 @@ class OrderListAdapter(
)
)
}

VIEW_TYPE_LOADING -> {
val view = inflater.inflate(R.layout.skeleton_order_list_item_auto, parent, false)
LoadingViewHolder(view)
}

VIEW_TYPE_SECTION_HEADER -> {
SectionHeaderViewHolder(
OrderListHeaderBinding.inflate(
Expand All @@ -74,6 +78,7 @@ class OrderListAdapter(
)
)
}

else -> {
// Fail fast if a new view type is added so we can handle it
throw IllegalStateException("The view type '$viewType' needs to be handled")
Expand All @@ -97,7 +102,9 @@ class OrderListAdapter(
allOrderIds,
isActivated = tracker?.isSelected(item.orderId) ?: false
)
orderIdAndPosition[item.orderId] = position
}

is SectionHeaderViewHolder -> {
if (BuildConfig.DEBUG && item !is SectionHeader) {
error(
Expand All @@ -107,6 +114,7 @@ class OrderListAdapter(
}
holder.onBind((item as SectionHeader))
}

else -> {}
}
}
Expand All @@ -126,7 +134,11 @@ class OrderListAdapter(
fun setOrderStatusOptions(orderStatusOptions: Map<String, WCOrderStatusModel>) {
if (orderStatusOptions.keys != activeOrderStatusMap.keys) {
this.activeOrderStatusMap = orderStatusOptions
notifyDataSetChanged()
for (position in 0 until itemCount) {
if (getItem(position) is OrderListItemUI) {
notifyItemChanged(position)
}
}
}
}

Expand Down Expand Up @@ -184,6 +196,7 @@ class OrderListAdapter(
viewBinding.root.context.getColor(R.color.color_item_selected)
)
}

else -> {
viewBinding.orderItemLayout.setBackgroundColor(Color.TRANSPARENT)
}
Expand All @@ -209,6 +222,7 @@ class OrderListAdapter(
extras[SwipeToComplete.OLD_STATUS] = orderItemUI.status

this.itemView.setOnClickListener {
if (shouldPreventDetailNavigation(orderId)) return@setOnClickListener
listener.openOrderDetail(
orderId = orderItemUI.orderId,
allOrderIds = allOrderIds,
Expand All @@ -218,6 +232,23 @@ class OrderListAdapter(
}
}

// Some edge cases in order selection mode, like tapping the screen with 4 fingers or using TalkBack,
// cause the order's onClick listener to gain focus over the selection tracker.
// This quick fix will prevent the app from entering an unexpected status when the app is in selection mode.
private fun shouldPreventDetailNavigation(orderId: Long): Boolean {
if (tracker?.selection?.size() != 0) {
tracker?.let { selectionTracker ->
if (selectionTracker.isSelected(orderId)) {
selectionTracker.deselect(orderId)
} else {
selectionTracker.select(orderId)
}
}
return true
}
return false
}

/**
* Converts the order status label into an [OrderStatusTag], creates the associated [TagView],
* and add it to the holder. No need to trim the label text since this is done in [OrderStatusTag]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,11 @@ class OrderListFragment :

private fun adjustLayoutForNonTablet(savedInstanceState: Bundle?) {
if (wasLastWindowSizeLargerThanCompact(savedInstanceState)) {
displayDetailPaneOnly()
if (viewModel.isSelecting()) {
displayListPaneOnly()
} else {
displayDetailPaneOnly()
}
} else {
displayListPaneOnly()
}
Expand Down Expand Up @@ -406,6 +410,23 @@ class OrderListFragment :
outState.putBoolean(LAST_WINDOW_SIZE_WAS_LARGER_THAN_COMPACT, true)
}
}
tracker?.onSaveInstanceState(outState)
viewModel.orderIdAndPositionBackup =
((binding.orderListView.ordersList.adapter as? OrderListAdapter)?.orderIdAndPosition ?: emptyMap())
as MutableMap<Long, Int>
}

override fun onViewStateRestored(savedInstanceState: Bundle?) {
tracker?.run {
onRestoreInstanceState(savedInstanceState)
(binding.orderListView.ordersList.adapter as? OrderListAdapter)?.orderIdAndPosition =
viewModel.orderIdAndPositionBackup
if (hasSelection()) {
setItemsSelected(selection.toList(), true)
}
}

super.onViewStateRestored(savedInstanceState)
}

override fun onDestroyView() {
Expand All @@ -414,6 +435,8 @@ class OrderListFragment :
searchView = null
orderListMenu = null
searchMenuItem = null
tracker = null
actionMode = null
super.onDestroyView()
_binding = null
}
Expand Down Expand Up @@ -608,9 +631,11 @@ class OrderListFragment :
actionText = event.actionText,
action = event.action
)

is OrderListViewModel.OrderListEvent.RetryLoadingOrders -> refreshOrders()
is OrderListViewModel.OrderListEvent.OpenOrderCreationWithSimplePaymentsMigration ->
openOrderCreationFragment(indicateSimplePaymentsMigration = true)

is OrderListViewModel.OrderListEvent.ShowUpdateStatusDialog -> {
showBulkUpdateStatusDialog(event.currentStatus, event.orderStatusList)
}
Expand All @@ -627,6 +652,7 @@ class OrderListFragment :
viewModel.trashOrder(event.orderId)
selectedOrder.selectOrder(-1L)
}

else -> event.isHandled = false
}
}
Expand Down Expand Up @@ -893,32 +919,13 @@ class OrderListFragment :
binding.orderListView.submitPagedList(pagedListData)
}

// Some edge cases in order selection mode, like tapping the screen with 4 fingers or using TalkBack,
// cause the order's onClick listener to gain focus over the selection tracker.
// This quick fix will prevent the app from entering an unexpected status when the app is in selection mode.
private fun shouldPreventDetailNavigation(orderId: Long): Boolean {
if (viewModel.isSelecting()) {
tracker?.let { selectionTracker ->
if (selectionTracker.isSelected(orderId)) {
selectionTracker.deselect(orderId)
} else {
selectionTracker.select(orderId)
}
}
return true
}
return false
}

override fun openOrderDetail(
orderId: Long,
allOrderIds: List<Long>,
orderStatus: String,
sharedView: View?,
startPaymentsFlow: Boolean,
) {
if (shouldPreventDetailNavigation(orderId)) return

viewModel.trackOrderClickEvent(
orderId,
orderStatus,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ class OrderListViewModel @Inject constructor(

val orderId: LiveData<Long> = savedState.getLiveData<Long>("orderId")

var orderIdAndPositionBackup = mutableMapOf<Long, Int>()

private val _emptyViewType: ThrottleLiveData<EmptyViewType?> by lazy {
ThrottleLiveData(
offset = EMPTY_VIEW_THROTTLE,
Expand Down

0 comments on commit 37c5583

Please sign in to comment.