OrderStateFragment.kt (4794B)
1 /* 2 * This file is part of GNU Taler 3 * (C) 2020 Taler Systems S.A. 4 * 5 * GNU Taler is free software; you can redistribute it and/or modify it under the 6 * terms of the GNU General Public License as published by the Free Software 7 * Foundation; either version 3, or (at your option) any later version. 8 * 9 * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY 10 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License along with 14 * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 17 package net.taler.merchantpos.order 18 19 import android.os.Bundle 20 import android.view.LayoutInflater 21 import android.view.View 22 import android.view.ViewGroup 23 import androidx.fragment.app.Fragment 24 import androidx.fragment.app.activityViewModels 25 import androidx.recyclerview.selection.SelectionPredicates 26 import androidx.recyclerview.selection.SelectionTracker 27 import androidx.recyclerview.selection.StorageStrategy 28 import androidx.recyclerview.widget.LinearLayoutManager 29 import net.taler.merchantpos.MainViewModel 30 import net.taler.merchantpos.databinding.FragmentOrderStateBinding 31 import net.taler.merchantpos.order.OrderAdapter.OrderLineLookup 32 33 class OrderStateFragment : Fragment() { 34 35 private val viewModel: MainViewModel by activityViewModels() 36 private val orderManager by lazy { viewModel.orderManager } 37 private val liveOrder by lazy { orderManager.getOrder(orderManager.currentOrderId.value!!) } 38 39 private lateinit var ui: FragmentOrderStateBinding 40 private val adapter = OrderAdapter() 41 private var tracker: SelectionTracker<String>? = null 42 43 override fun onCreateView( 44 inflater: LayoutInflater, 45 container: ViewGroup?, 46 savedInstanceState: Bundle? 47 ): View? { 48 ui = FragmentOrderStateBinding.inflate(inflater, container, false) 49 return ui.root 50 } 51 52 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 53 ui.orderList.apply { 54 adapter = this@OrderStateFragment.adapter 55 layoutManager = LinearLayoutManager(requireContext()) 56 } 57 val detailsLookup = OrderLineLookup(ui.orderList) 58 val tracker = SelectionTracker.Builder( 59 "order-selection-id", 60 ui.orderList, 61 adapter.keyProvider, 62 detailsLookup, 63 StorageStrategy.createStringStorage() 64 ).withSelectionPredicate( 65 SelectionPredicates.createSelectSingleAnything() 66 ).build() 67 savedInstanceState?.let { tracker.onRestoreInstanceState(it) } 68 adapter.tracker = tracker 69 this.tracker = tracker 70 if (savedInstanceState == null) { 71 // select last selected order line when re-creating this fragment 72 // do it before attaching the tracker observer 73 liveOrder.selectedProductKey?.let { tracker.select(it) } 74 } 75 tracker.addObserver(object : SelectionTracker.SelectionObserver<String>() { 76 override fun onItemStateChanged(key: String, selected: Boolean) { 77 super.onItemStateChanged(key, selected) 78 val item = if (selected) adapter.getItemByKey(key) else null 79 liveOrder.selectOrderLine(item) 80 } 81 }) 82 liveOrder.order.observe(viewLifecycleOwner) { order -> 83 if (order == null) return@observe 84 onOrderChanged(order, tracker) 85 } 86 } 87 88 override fun onSaveInstanceState(outState: Bundle) { 89 super.onSaveInstanceState(outState) 90 tracker?.onSaveInstanceState(outState) 91 } 92 93 private fun onOrderChanged(order: Order, tracker: SelectionTracker<String>) { 94 adapter.setItems(order.products) { 95 liveOrder.lastAddedProduct?.let { 96 val position = adapter.findPosition(it) 97 if (position >= 0) { 98 ui.orderList.scrollToPosition(position) 99 ui.orderList.post { this.tracker?.select(it.id) } 100 return@setItems 101 } 102 } 103 val selectedKey = tracker.selection.firstOrNull() 104 val selectedProduct = selectedKey?.let { key -> 105 order.products.find { it.id == key } 106 } 107 if (selectedProduct == null) { 108 val fallbackProduct = order.products.lastOrNull() 109 tracker.clearSelection() 110 if (fallbackProduct == null) { 111 liveOrder.selectOrderLine(null) 112 } else { 113 ui.orderList.post { this.tracker?.select(fallbackProduct.id) } 114 } 115 } 116 } 117 } 118 119 }