moffpage

AppealDetailsDataBindableFragment.kt

May 18th, 2021
787
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package com.evrika.courier.presentation.main_container.appeal_details
  2.  
  3. import kotlinx.coroutines.flow.onEach
  4.  
  5. import android.os.Bundle
  6. import android.util.Log
  7. import android.view.View
  8. import android.widget.Button
  9. import android.widget.TextView
  10. import android.widget.ImageButton
  11.  
  12. import androidx.core.os.bundleOf
  13. import androidx.annotation.LayoutRes
  14. import androidx.fragment.app.setFragmentResult
  15. import androidx.recyclerview.widget.RecyclerView
  16.  
  17. import org.koin.core.parameter.parametersOf
  18. import org.koin.androidx.viewmodel.ext.android.viewModel
  19.  
  20. import com.google.android.material.dialog.MaterialAlertDialogBuilder
  21.  
  22. import com.evrika.courier.R
  23. import com.evrika.courier.data.entity.AppealStatus
  24. import com.evrika.courier.data.entity.AppealDetails.PurchaseProof.Nomenclature
  25. import com.evrika.courier.databinding.AppealDetailsLayoutBinding
  26. import com.evrika.courier.utilities.extensions.showSnackbar
  27. import com.evrika.courier.utilities.extensions.autoClearedValue
  28. import com.evrika.courier.utilities.extensions.launchWhenResumedIn
  29. import com.evrika.courier.utilities.extensions.launchWhenStartedIn
  30. import com.evrika.courier.utilities.extensions.requireArgumentsLazily
  31. import com.evrika.courier.utilities.extensions.addOnBackPressedCallback
  32. import com.evrika.courier.utilities.base.fragment.BaseDataBindableFragment
  33. import com.evrika.courier.utilities.base.recycler_view.BaseRecyclerViewListAdapter
  34. import com.evrika.courier.utilities.activity_result_launchers.CallPermissionRequestLauncher
  35. import com.evrika.courier.presentation.main_container.appeal_details.AppealDetailsViewModel.Event
  36. import com.evrika.courier.presentation.main_container.incoming_appeals.IncomingAppealsDataBindableFragment
  37.  
  38. class AppealDetailsDataBindableFragment : BaseDataBindableFragment<AppealDetailsViewModel, AppealDetailsLayoutBinding>(
  39.     R.layout.appeal_details_layout
  40. ) {
  41.     override val viewModel by viewModel<AppealDetailsViewModel> { parametersOf(appealNumber) }
  42.  
  43.     private val backButton: ImageButton get() = viewBinding.backButton
  44.     private val changeAppealStatusButton: Button get() = viewBinding.changeAppealStatusButton
  45.     private val nomenclaturesRecyclerView: RecyclerView get() = viewBinding.nomenclaturesRecyclerView
  46.     private val receiverPhoneNumberTextView: TextView get() = viewBinding.receiverPhoneNumberTextView
  47.  
  48.     private val appealNumber by requireArgumentsLazily<String>(APPEAL_NUMBER_KEY)
  49.  
  50.     private lateinit var callPermissionRequestLauncher: CallPermissionRequestLauncher
  51.  
  52.     private var nomenclaturesRecyclerViewAdapter by autoClearedValue<NomenclaturesListAdapter>()
  53.  
  54.     override fun onCreate(savedInstanceState: Bundle?) {
  55.         super.onCreate(savedInstanceState)
  56.         callPermissionRequestLauncher = CallPermissionRequestLauncher(
  57.             registry = requireActivity().activityResultRegistry,
  58.             onPermissionGranted = { viewModel.confirmCallToReceiver() },
  59.             onPermissionDenied = { notifyUserDeniedCalling() }
  60.         )
  61.         lifecycle.addObserver(callPermissionRequestLauncher)
  62.         requireActivity().addOnBackPressedCallback { popAndStopTimerIfNeeded() }
  63. //              sharedElementEnterTransition = MaterialContainerTransform().apply {
  64. //                      drawingViewId = R.id.root_fragment_container_view
  65. //                      duration = resources.getInteger(R.integer.material_container_transform_transition_duration).toLong()
  66. //                      scrimColor = Color.TRANSPARENT
  67. ////                    setAllContainerColors(requireContext())
  68. //              }
  69.     }
  70.  
  71.     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
  72.         super.onViewCreated(view, savedInstanceState)
  73.  
  74.         nomenclaturesRecyclerViewAdapter = NomenclaturesListAdapter()
  75.         nomenclaturesRecyclerView.adapter = nomenclaturesRecyclerViewAdapter
  76.  
  77.         backButton.setOnClickListener { popAndStopTimerIfNeeded() }
  78.         receiverPhoneNumberTextView.setOnClickListener { callPermissionRequestLauncher.requestPermission() }
  79.  
  80.         with(viewModel) {
  81.             eventsFlow.onEach { event ->
  82.                 when (event) {
  83. //                    Event.FailedToRetrieveAppeal -> tellParentCannotRetrieveAppealDetails()
  84. //                    is Event.ShowCountdown -> showCountdown(
  85. //                        event.duration,
  86. //                        event.interval
  87. //                    ) { popAndStopTimerIfNeeded() }
  88.                     is Event.ShowStatusChooser -> showStatusChooser(event.appealStatuses)
  89.                     is Event.ConfirmCallReceiver -> confirmCallToReceiver(event.receiverPhoneNumber)
  90.                     is Event.ConfirmShowStoreLocation -> confirmShowStoreLocation(event.storeLocation)
  91.                     is Event.ConfirmShowDestinationLocation -> confirmShowDestinationLocation(event.destinationLocation)
  92.                 }
  93.             }.launchWhenStartedIn(this@AppealDetailsDataBindableFragment)
  94.  
  95.             appealState.onEach { appeal ->
  96.                 viewBinding.appeal = appeal
  97.                 viewBinding.canChangeAppealStatus = (appeal.status != AppealStatus.DELIVERED) || (appeal.status != AppealStatus.DENIED)
  98.                 nomenclaturesRecyclerViewAdapter.submitList(appeal.purchaseProof.nomenclatures)
  99.             }.launchWhenResumedIn(this@AppealDetailsDataBindableFragment)
  100.  
  101.             checkedAppealStatusString.onEach { appealStatusStringResourceId ->
  102.                 changeAppealStatusButton.text = requireContext().resources.getString(appealStatusStringResourceId)
  103.             }.launchWhenStartedIn(this@AppealDetailsDataBindableFragment)
  104.  
  105.             appealStatusChangeResponseFlow.onEach { result ->
  106.                 val (response, error) = result
  107.                 if (response != null) {
  108.                     showSnackbar(
  109.                         view = viewBinding.root,
  110.                         message = requireContext().resources.getString(R.string.successful_status_change)
  111.                     )
  112.                 } else if (error != null) {
  113.                     showSnackbar(
  114.                         view = viewBinding.root,
  115.                         message = requireContext().resources.getString(error.messageResourceId)
  116.                     )
  117.                 }
  118.             }.launchWhenStartedIn(this@AppealDetailsDataBindableFragment)
  119.  
  120.             notificationReceivalResponseFlow.onEach { result ->
  121.                 val (payload, error) = result
  122.                 if (payload != null) {
  123.                     showSnackbar(
  124.                         view = viewBinding.root,
  125.                         message = requireContext().resources.getString(R.string.receiver_notified_with_success)
  126.                     )
  127.                 } else if (error != null) {
  128.                     showSnackbar(
  129.                         view = viewBinding.root,
  130.                         message = requireContext().resources.getString(error.messageResourceId)
  131.                     )
  132.                 }
  133.             }.launchWhenStartedIn(this@AppealDetailsDataBindableFragment)
  134.         }
  135.     }
  136.  
  137.     private fun confirmCallToReceiver(receiverPhoneNumber: String) {
  138.         showConfirmationDialog(
  139.             title = requireContext().resources.getString(R.string.contact_someone, receiverPhoneNumber),
  140.             confirmString = requireContext().resources.getString(R.string.call),
  141.             action = { viewModel.call() }
  142.         )
  143.     }
  144.  
  145.     private fun confirmShowStoreLocation(storeLocation: String) {
  146.         showConfirmationDialog(
  147.             title = requireContext().resources.getString(R.string.navigate_to, storeLocation),
  148.             confirmString = requireContext().resources.getString(R.string.navigate),
  149.             action = { viewModel.showStoreLocationInMaps() }
  150.         )
  151.     }
  152.  
  153.     private fun confirmShowDestinationLocation(destinationLocation: String) {
  154.         showConfirmationDialog(
  155.             title = requireContext().resources.getString(R.string.navigate_to, destinationLocation),
  156.             confirmString = requireContext().resources.getString(R.string.navigate),
  157.             action = { viewModel.showDestinationLocationInMaps() }
  158.         )
  159.     }
  160.  
  161.     private fun notifyUserDeniedCalling() {
  162.         val messageView = TextView(requireContext()).apply {
  163.             text = requireContext().resources.getString(
  164.                 R.string.permission_management_suggestion,
  165.                 context.resources.getString(R.string.calls),
  166.                 context.resources.getString(R.string.manager)
  167.             )
  168.             textSize = 16F
  169.             setPadding(45, 0, 45, 0)
  170.         }
  171.         MaterialAlertDialogBuilder(requireContext())
  172.             .setTitle(requireContext().resources.getString(R.string.permission_needed))
  173.             .setPositiveButton(R.string.go_to_settings) { _, _ -> viewModel.navigateToApplicationSettings() }
  174.             .setView(messageView)
  175.             .create()
  176.             .show()
  177.     }
  178.  
  179.     private fun showCountdown(duration: Long, interval: Long, onCountdownFinish: () -> Unit) {
  180.         onCountdownFinish()
  181.  
  182. //              val snackbar = Snackbar.make(
  183. //                      viewBinding.root,
  184. //                      requireContext().resources.getString(R.string.count_down),
  185. //                      duration.toInt()
  186. //              )
  187. //              snackbar.show()
  188. //              val timer = object : CountDownTimer(duration, interval) {
  189. //                      override fun onTick(millisUntilFinished: Long) {
  190. //                              val remaining = (millisUntilFinished / interval).toInt()
  191. //                              snackbar.setText(requireContext().resources.getString(R.string.count_down, remaining))
  192. //                      }
  193. //                      override fun onFinish() {
  194. //                              snackbar.dismiss()
  195. //                              onCountdownFinish()
  196. //                      }
  197. //              }
  198. //              snackbar.setAction(R.string.undo) {
  199. //                      timer.cancel()
  200. //                      snackbar.dismiss()
  201. //              }
  202. //              timer.start()
  203.     }
  204.  
  205.     private fun showConfirmationDialog(title: String, confirmString: String, action: () -> Unit) {
  206.         MaterialAlertDialogBuilder(requireContext())
  207.             .setTitle(title)
  208.             .setMessage(R.string.are_you_sure)
  209.             .setPositiveButton(confirmString) { _, _ -> action() }
  210.             .setNegativeButton(android.R.string.cancel) { _, _ -> }
  211.             .create()
  212.             .show()
  213.     }
  214.  
  215.     private fun showStatusChooser(statuses: Array<out AppealStatus>) {
  216.         MaterialAlertDialogBuilder(requireContext())
  217.             .setSingleChoiceItems(
  218.                 statuses.map { status ->
  219.                     requireContext().resources.getString(status.localizedDescriptionResourceId)
  220.                 }.toTypedArray(),
  221.                 -1
  222.             ) { dialog, checkedIndex ->
  223.                 viewModel.changeAppealStatus(statuses[checkedIndex])
  224.                 dialog.dismiss()
  225.             }.create()
  226.             .show()
  227.     }
  228.  
  229.     private fun tellParentCannotRetrieveAppealDetails() {
  230. //        setFragmentResult(
  231. //            IncomingAppealsDataBindableFragment.APPEAL_DETAILS_NOT_RETRIEVED_ACTION_REQUEST_KEY,
  232. //            Bundle().apply { putBoolean(IncomingAppealsDataBindableFragment.APPEAL_NUMBER_KEY, false) }
  233. //        )
  234.     }
  235.  
  236.     //  @OptIn(ExperimentalStdlibApi::class)
  237.     private fun popAndStopTimerIfNeeded() {
  238. //        val bundle = Bundle()
  239. //        bundle.putString(IncomingAppealsDataBindableFragment.APPEAL_NUMBER_KEY, appealNumber)
  240. //        bundle.putString(
  241. //            IncomingAppealsDataBindableFragment.APPEAL_STATUS_KEY,
  242. //            viewModel.checkedAppealStatusState.value.name.toLowerCase()
  243. //        )
  244. ////            val appliedBundle = bundle.apply {
  245. ////                    putString(IncomingAppealsDataBindableFragment.APPEAL_NUMBER_KEY, appealNumber)
  246. ////                    putString(IncomingAppealsDataBindableFragment.APPEAL_STATUS_KEY, viewModel.checkedAppealStatusState.value.name.lowercase())
  247. ////            }
  248. //        setFragmentResult(
  249. //            IncomingAppealsDataBindableFragment.REMOVE_REQUESTED_APPEAL_ACTION_REQUEST_KEY,
  250. ////                    bundleOf(
  251. ////                            IncomingAppealsDataBindableFragment.APPEAL_NUMBER_KEY to appealNumber,
  252. ////                            IncomingAppealsDataBindableFragment.APPEAL_STATUS_KEY to viewModel.checkedAppealStatusState.value.name.lowercase()
  253. ////                    )
  254. //            bundle
  255. //        )
  256.         viewModel.pop()
  257.     }
  258.  
  259.     companion object {
  260.         private const val APPEAL_NUMBER_KEY = "APPEAL_NUMBER_KEY"
  261.  
  262.         fun newInstance(appealNumber: String): AppealDetailsDataBindableFragment =
  263.             AppealDetailsDataBindableFragment().apply { arguments = bundleOf(APPEAL_NUMBER_KEY to appealNumber) }
  264.     }
  265. }
  266.  
  267. private class NomenclaturesListAdapter : BaseRecyclerViewListAdapter<Nomenclature>() {
  268.     @LayoutRes
  269.     override fun obtainLayoutResourceId(position: Int): Int = R.layout.nomenclature_cell_layout
  270. }
RAW Paste Data