Improve DeletableItemFragment and bankroll deletion

dev
Aurelien Hubert 7 years ago
parent 0bc502e468
commit 955206f00d
  1. 95
      app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt
  2. 1
      app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt
  3. 59
      app/src/main/java/net/pokeranalytics/android/ui/fragment/DeletableItemFragment.kt
  4. 4
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/CustomizableRowRepresentable.kt
  5. 2
      app/src/main/res/layout/fragment_data_list.xml

@ -6,10 +6,8 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.recyclerview.widget.LinearLayoutManager
import com.github.mikephil.charting.data.LineDataSet
import io.realm.Realm
import io.realm.RealmObject
import io.realm.RealmResults
import kotlinx.android.synthetic.main.fragment_bankroll.*
@ -25,7 +23,7 @@ import net.pokeranalytics.android.calculus.bankroll.BankrollCalculator
import net.pokeranalytics.android.calculus.bankroll.BankrollReport
import net.pokeranalytics.android.calculus.bankroll.BankrollReportSetup
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.interfaces.Deletable
import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.model.realm.Bankroll
import net.pokeranalytics.android.ui.activity.BankrollDetailsActivity
import net.pokeranalytics.android.ui.activity.DataListActivity
@ -66,9 +64,9 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
private var rows: ArrayList<RowRepresentable> = ArrayList()
private var bankrollReportForRow: HashMap<RowRepresentable, BankrollReport> = HashMap()
private var deletedItem: RealmObject? = null
private var lastDeletedItemPosition: Int = 0
private var lastItemClickedPosition: Int = 0
private var lastItemClickedId: String = ""
private var deletedRow: RowRepresentable? = null
// Life Cycle
@ -91,7 +89,7 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
if (needToDeleteItem) {
GlobalScope.launch(Dispatchers.Main) {
delay(300)
deleteItem(lastItemClickedPosition)
deleteItem(bankrollAdapter, LiveData.BANKROLL.items(getRealm()), lastItemClickedId)
}
}
} else if (requestCode == REQUEST_CODE_CREATE && resultCode == Activity.RESULT_OK) {
@ -115,6 +113,7 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
if (bankrollReportForRow.containsKey(row)) {
bankrollReportForRow[row]?.let { bankrollReport ->
lastItemClickedPosition = position
lastItemClickedId = (row as Identifiable).id
BankrollDetailsActivity.newInstanceForResult(this, bankrollReport, REQUEST_CODE_DETAILS)
}
}
@ -136,6 +135,9 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
launch(Dispatchers.Main) {
// TODO: Improve that
// We are in the main thread...
val startDate = Date()
// Graph
@ -152,14 +154,13 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
val bankrolls = LiveData.BANKROLL.items(getRealm()) as RealmResults<Bankroll>
bankrolls.forEach {
Timber.d("Bankroll: ${it.name} => isValidForDelete: ${it.isValidForDelete(Realm.getDefaultInstance())}")
val bankrollReportSetup = BankrollReportSetup(it)
bankrolls.forEach { bankroll ->
val bankrollReportSetup = BankrollReportSetup(bankroll)
val bankrollReport = BankrollCalculator.computeReport(getRealm(), bankrollReportSetup)
val computedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.total)
val row = CustomizableRowRepresentable(RowViewType.TITLE_VALUE_ARROW, title = it.name, computedStat = computedStat, isSelectable = true)
val row =
CustomizableRowRepresentable(RowViewType.TITLE_VALUE_ARROW, title = bankroll.name, computedStat = computedStat, isSelectable = true)
row.id = bankroll.id
rows.add(row)
bankrollReportForRow[row] = bankrollReport
@ -201,68 +202,26 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
}
}
/**
* Delete item
*/
private fun deleteItem(position: Int) {
//TODO: Get bankroll from bankrollReport and delete it
if (isDetached || activity == null) {
return
override fun updateUIAfterDeletion(itemPosition: Int) {
lastItemClickedPosition = rows.indexOfFirst { if (it is Identifiable) it.id == lastItemClickedId else false }
deletedRow = rows.find { if (it is Identifiable) it.id == lastItemClickedId else false }
rows.removeAt(lastItemClickedPosition)
bankrollAdapter.notifyItemRemoved(lastItemClickedPosition)
}
// Save the delete position & create a copy of the object
val bankrollReport = bankrollReportForRow[rowRepresentableForPosition(position)]
val mRecentlyDeletedItem = bankrollReport?.setup?.bankroll
lastDeletedItemPosition = position
if (mRecentlyDeletedItem is Bankroll) {
val deletableItem = (mRecentlyDeletedItem as Deletable)
// Check if the object is valid for the deletion
if (deletableItem.isValidForDelete(this.getRealm())) {
deletedItem = getRealm().copyFromRealm(mRecentlyDeletedItem)
getRealm().executeTransaction {
mRecentlyDeletedItem.deleteFromRealm()
}
//bankrollAdapter.notifyItemRemoved(position)
//showUndoSnackBar()
override fun updateUIAfterUndoDeletion(newItem: RealmObject) {
//TODO: Refresh bankrolls
initData()
// TODO: Improve that
// We are recreating a Bankroll report because the last one if invalid => the bankroll of the setup has been deleted
} else {
bankrollAdapter.notifyItemChanged(position)
val status = deletableItem.getDeleteStatus(this.getRealm())
val errorMessage = deletableItem.getFailedDeleteMessage(status)
val builder = AlertDialog.Builder(requireContext())
.setMessage(errorMessage)
.setNegativeButton(R.string.ok, null)
builder.show()
}
}
}
deletedRow?.let { row ->
val bankrollReportSetup = BankrollReportSetup(newItem as Bankroll)
val bankrollReport = BankrollCalculator.computeReport(getRealm(), bankrollReportSetup)
bankrollReportForRow[row] = bankrollReport
/**
* Show undo snack bar
*/
private fun showUndoSnackBar() {
/*
val message = String.format(getString(R.string.data_deleted), getString(R.string.bankroll))
val snackBar = Snackbar.make(coordinatorLayout, message, Snackbar.LENGTH_INDEFINITE)
snackBar.setAction(R.string.cancel) {
getRealm().executeTransaction { realm ->
deletedItem?.let {
realm.copyToRealmOrUpdate(it)
bankrollAdapter.notifyItemInserted(lastDeletedItemPosition)
rows.add(lastItemClickedPosition, row)
bankrollAdapter.notifyItemInserted(lastItemClickedPosition)
}
}
}
snackBar.show()
*/
}
}

@ -40,7 +40,6 @@ class DataListFragment : DeletableItemFragment(), LiveRowRepresentableDataSource
private lateinit var dataListAdapter: RowRepresentableAdapter
private var lastItemClickedId: String = ""
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_data_list, container, false)

@ -1,22 +1,45 @@
package net.pokeranalytics.android.ui.fragment
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.google.android.material.snackbar.Snackbar
import io.realm.RealmObject
import kotlinx.android.synthetic.main.fragment_data_list.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.interfaces.Deletable
import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.fragment.components.RealmFragment
/**
* Deletable Item Fragment
* Don't forget to add a CoordinatorLayout at the top of your XML if you want to display correctly the snack bar
*/
open class DeletableItemFragment : RealmFragment() {
private var deletedItem: RealmObject? = null
private var lastDeletedItemPosition: Int = 0
private var dataListAdapter: RowRepresentableAdapter? = null
private var coordinatorLayout: CoordinatorLayout? = null
private var snackBar: Snackbar? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
this.coordinatorLayout = view.findViewById(R.id.coordinatorLayout)
}
override fun onPause() {
super.onPause()
snackBar?.dismiss()
}
/**
* Delete item
* [dataListAdapter]: Adapter to update
* [items]: List of items which contains the element to delete
* [itemId]: Id of the item to delete
* [container]: View to display the Snackbar
*/
fun deleteItem(dataListAdapter: RowRepresentableAdapter, items: List<*>, itemId: String) {
@ -24,6 +47,8 @@ open class DeletableItemFragment : RealmFragment() {
return
}
this.dataListAdapter = dataListAdapter
// Save the delete position & create a copy of the object
val itemPosition = items.indexOfFirst { (it as Identifiable).id == itemId }
val itemToDelete = items.find { (it as Identifiable).id == itemId }
@ -39,8 +64,8 @@ open class DeletableItemFragment : RealmFragment() {
getRealm().executeTransaction {
itemToDelete.deleteFromRealm()
}
dataListAdapter.notifyItemRemoved(itemPosition)
showUndoSnackBar(dataListAdapter)
updateUIAfterDeletion(itemPosition)
showUndoSnackBar()
} else {
dataListAdapter.notifyItemChanged(itemPosition)
val status = deletableItem.getDeleteStatus(this.getRealm())
@ -56,18 +81,34 @@ open class DeletableItemFragment : RealmFragment() {
/**
* Show undo snack bar
*/
private fun showUndoSnackBar(dataListAdapter: RowRepresentableAdapter) {
private fun showUndoSnackBar() {
val message = String.format(getString(R.string.data_deleted))
val snackBar = Snackbar.make(constraintLayout, message, Snackbar.LENGTH_INDEFINITE)
snackBar.setAction(R.string.cancel) {
this.coordinatorLayout?.let { view ->
snackBar = Snackbar.make(view, message, Snackbar.LENGTH_INDEFINITE)
snackBar?.setAction(R.string.cancel) {
getRealm().executeTransaction { realm ->
deletedItem?.let {
realm.copyToRealmOrUpdate(it)
dataListAdapter.notifyItemInserted(lastDeletedItemPosition)
val item = realm.copyToRealmOrUpdate(it)
updateUIAfterUndoDeletion(item)
}
}
}
snackBar?.show()
}
snackBar.show()
}
/**
* Called once the object has been deleted
*/
open fun updateUIAfterDeletion(itemPosition: Int) {
dataListAdapter?.notifyItemRemoved(itemPosition)
}
/**
* Called once the object has been restored
*/
open fun updateUIAfterUndoDeletion(newItem: RealmObject) {
dataListAdapter?.notifyItemInserted(lastDeletedItemPosition)
}
}

@ -2,6 +2,7 @@ package net.pokeranalytics.android.ui.view.rowrepresentable
import android.content.Context
import net.pokeranalytics.android.calculus.ComputedStat
import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
@ -15,7 +16,7 @@ class CustomizableRowRepresentable(
var value: String? = null,
var computedStat: ComputedStat? = null,
var isSelectable: Boolean? = false
) : RowRepresentable {
) : RowRepresentable, Identifiable {
override fun localizedTitle(context: Context): String {
@ -30,4 +31,5 @@ class CustomizableRowRepresentable(
override val viewType: Int = customViewType?.ordinal ?: RowViewType.HEADER_TITLE.ordinal
override var id: String = ""
}

@ -2,7 +2,7 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:id="@+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">

Loading…
Cancel
Save