Merge branch 'master' of gitlab.com:stax-river/poker-analytics

# Conflicts:
#	app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
feature/top10
Aurelien Hubert 7 years ago
commit 75992918a8
  1. 6
      app/src/main/java/net/pokeranalytics/android/model/LiveData.kt
  2. 18
      app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt
  3. 18
      app/src/main/java/net/pokeranalytics/android/model/realm/Game.kt
  4. 11
      app/src/main/java/net/pokeranalytics/android/model/realm/Location.kt
  5. 21
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  6. 11
      app/src/main/java/net/pokeranalytics/android/model/realm/TournamentFeature.kt
  7. 11
      app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt
  8. 1
      app/src/main/java/net/pokeranalytics/android/ui/adapter/components/LiveDataAdapter.kt
  9. 72
      app/src/main/java/net/pokeranalytics/android/ui/adapter/components/RowRepresentableAdapter.kt
  10. 32
      app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt
  11. 11
      app/src/main/java/net/pokeranalytics/android/ui/fragment/EditableDataFragment.kt
  12. 56
      app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt
  13. 46
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListFragment.kt
  14. 53
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListGameFragment.kt
  15. 8
      app/src/main/java/net/pokeranalytics/android/ui/view/RowRepresentable.kt
  16. 6
      app/src/main/java/net/pokeranalytics/android/ui/view/RowRepresentableDiffCallback.kt
  17. 35
      app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt

@ -16,6 +16,8 @@ interface ObjectSavable {
fun isValidForSave(): Boolean { fun isValidForSave(): Boolean {
return true return true
} }
fun uniqueIdentifier(): String
} }
/** /**
@ -64,8 +66,8 @@ enum class LiveData : Localizable {
} }
} }
fun deleteData(realm:Realm, data:LiveDataDataSource) { fun deleteData(realm:Realm, data:ObjectSavable) {
realm.where(this.relatedEntity).equalTo("id", data.primaryKey).findAll().deleteAllFromRealm() realm.where(this.relatedEntity).equalTo("id", data.uniqueIdentifier()).findAll().deleteAllFromRealm()
} }
fun updateOrCreate(realm:Realm, primaryKey:String?): RealmObject { fun updateOrCreate(realm:Realm, primaryKey:String?): RealmObject {

@ -8,15 +8,12 @@ import net.pokeranalytics.android.model.ObjectSavable
import net.pokeranalytics.android.ui.adapter.components.LiveDataDataSource import net.pokeranalytics.android.ui.adapter.components.LiveDataDataSource
import net.pokeranalytics.android.ui.adapter.components.RowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.components.RowRepresentableDataSource
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetData import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetData
import net.pokeranalytics.android.ui.view.BankrollRow import net.pokeranalytics.android.ui.view.*
import net.pokeranalytics.android.ui.view.RowEditable
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.SimpleRow
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
open class Bankroll(name: String = "") : RealmObject(), RowRepresentableDataSource, LiveDataDataSource, open class Bankroll(name: String = "") : RealmObject(), RowRepresentableDataSource,
RowEditable, ObjectSavable { RowEditable, ObjectSavable, RowRepresentable {
companion object { companion object {
fun newInstance() : Bankroll { fun newInstance() : Bankroll {
@ -42,8 +39,13 @@ open class Bankroll(name: String = "") : RealmObject(), RowRepresentableDataSour
// @todo rate management // @todo rate management
override val title: String get() = this.name override fun getDisplayName(): String {
override val primaryKey: String get() = this.id return this.name
}
override fun uniqueIdentifier(): String {
return this.id
}
override fun adapterRows(): ArrayList<RowRepresentable> { override fun adapterRows(): ArrayList<RowRepresentable> {
val rows = ArrayList<RowRepresentable>() val rows = ArrayList<RowRepresentable>()

@ -4,16 +4,15 @@ import android.text.InputType
import io.realm.RealmObject import io.realm.RealmObject
import io.realm.annotations.PrimaryKey import io.realm.annotations.PrimaryKey
import net.pokeranalytics.android.model.ObjectSavable import net.pokeranalytics.android.model.ObjectSavable
import net.pokeranalytics.android.ui.adapter.components.DisplayableDelegate
import net.pokeranalytics.android.ui.adapter.components.LiveDataDataSource import net.pokeranalytics.android.ui.adapter.components.LiveDataDataSource
import net.pokeranalytics.android.ui.adapter.components.RowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.components.RowRepresentableDataSource
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetData import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetData
import net.pokeranalytics.android.ui.view.GameRow import net.pokeranalytics.android.ui.view.*
import net.pokeranalytics.android.ui.view.RowEditable
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.SimpleRow
import java.util.* import java.util.*
open class Game : RealmObject(), RowRepresentableDataSource, LiveDataDataSource, RowEditable, ObjectSavable { open class Game : RealmObject(), RowRepresentableDataSource, RowEditable, ObjectSavable,
RowRepresentable {
@PrimaryKey @PrimaryKey
var id = UUID.randomUUID().toString() var id = UUID.randomUUID().toString()
@ -24,8 +23,13 @@ open class Game : RealmObject(), RowRepresentableDataSource, LiveDataDataSource,
// A shorter name for the game // A shorter name for the game
var shortName: String? = null var shortName: String? = null
override val title: String get() = this.name override fun getDisplayName(): String {
override val primaryKey: String get() = this.id return this.name
}
override fun uniqueIdentifier(): String {
return this.id
}
override fun adapterRows(): ArrayList<RowRepresentable> { override fun adapterRows(): ArrayList<RowRepresentable> {
val rows = ArrayList<RowRepresentable>() val rows = ArrayList<RowRepresentable>()

@ -13,7 +13,7 @@ import net.pokeranalytics.android.ui.view.SimpleRow
import java.util.* import java.util.*
open class Location : RealmObject(), RowRepresentableDataSource, LiveDataDataSource, RowEditable, ObjectSavable { open class Location : RealmObject(), RowRepresentableDataSource, RowEditable, ObjectSavable, RowRepresentable {
@PrimaryKey @PrimaryKey
var id = UUID.randomUUID().toString() var id = UUID.randomUUID().toString()
@ -27,8 +27,13 @@ open class Location : RealmObject(), RowRepresentableDataSource, LiveDataDataSou
// the latitude of the location // the latitude of the location
var latitude: Double? = null var latitude: Double? = null
override val title: String get() = this.name override fun getDisplayName(): String {
override val primaryKey: String get() = this.id return this.name
}
override fun uniqueIdentifier(): String {
return this.id
}
override fun adapterRows(): ArrayList<RowRepresentable> { override fun adapterRows(): ArrayList<RowRepresentable> {
val rows = ArrayList<RowRepresentable>() val rows = ArrayList<RowRepresentable>()

@ -10,7 +10,6 @@ import net.pokeranalytics.android.calculus.SessionInterface
import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.extensions.SessionState import net.pokeranalytics.android.model.extensions.SessionState
import net.pokeranalytics.android.model.extensions.getState import net.pokeranalytics.android.model.extensions.getState
import net.pokeranalytics.android.ui.adapter.components.LiveDataDataSource
import net.pokeranalytics.android.ui.adapter.components.RowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.components.RowRepresentableDataSource
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetData import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetData
import net.pokeranalytics.android.ui.view.RowEditable import net.pokeranalytics.android.ui.view.RowEditable
@ -24,8 +23,7 @@ import net.pokeranalytics.android.util.toCurrency
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
open class Session : RealmObject(), SessionInterface, RowRepresentableDataSource, LiveDataDataSource, open class Session : RealmObject(), SessionInterface, RowRepresentableDataSource, RowEditable {
RowEditable {
@PrimaryKey @PrimaryKey
var id = UUID.randomUUID().toString() var id = UUID.randomUUID().toString()
@ -153,7 +151,7 @@ open class Session : RealmObject(), SessionInterface, RowRepresentableDataSource
/** /**
* Return the formatted blinds * Return the formatted blinds
*/ */
fun getBlinds() : String { fun getBlinds(): String {
return if (cgSmallBlind == null) "--" else "$${cgSmallBlind?.round()}/${cgBigBlind?.round()}" return if (cgSmallBlind == null) "--" else "$${cgSmallBlind?.round()}/${cgBigBlind?.round()}"
} }
@ -202,7 +200,7 @@ open class Session : RealmObject(), SessionInterface, RowRepresentableDataSource
gameTitle += limit gameTitle += limit
} }
if (game != null) { if (game != null) {
gameTitle += game?.title gameTitle += game?.name
} }
return gameTitle return gameTitle
} }
@ -250,8 +248,10 @@ open class Session : RealmObject(), SessionInterface, RowRepresentableDataSource
return 0.0 return 0.0
} }
override fun adapterRows(): ArrayList<RowRepresentable> { override fun adapterRows(): ArrayList<RowRepresentable> {
val rows = ArrayList<RowRepresentable>() val rows = ArrayList<RowRepresentable>()
rows.clear()
rows.addAll(SessionRow.getRowsForState(getState())) rows.addAll(SessionRow.getRowsForState(getState()))
return rows return rows
} }
@ -265,9 +265,9 @@ open class Session : RealmObject(), SessionInterface, RowRepresentableDataSource
SessionRow.BUY_IN -> buyin.toCurrency() SessionRow.BUY_IN -> buyin.toCurrency()
SessionRow.CASHED_OUT -> result?.cashout?.toCurrency() ?: "--" SessionRow.CASHED_OUT -> result?.cashout?.toCurrency() ?: "--"
SessionRow.BLINDS -> getBlinds() SessionRow.BLINDS -> getBlinds()
SessionRow.GAME -> game?.title ?: "--" SessionRow.GAME -> game?.name ?: "--"
SessionRow.LOCATION -> location?.title ?: "--" SessionRow.LOCATION -> location?.name ?: "--"
SessionRow.BANKROLL -> bankroll?.title ?: "--" SessionRow.BANKROLL -> bankroll?.name ?: "--"
SessionRow.TABLE_SIZE -> tableSize?.toString() ?: "--" SessionRow.TABLE_SIZE -> tableSize?.toString() ?: "--"
SessionRow.START_DATE -> if (timeFrame != null) timeFrame?.startDate?.short() ?: "--" else "--" SessionRow.START_DATE -> if (timeFrame != null) timeFrame?.startDate?.short() ?: "--" else "--"
SessionRow.END_DATE -> if (timeFrame != null) timeFrame?.endDate?.short() ?: "--" else "--" SessionRow.END_DATE -> if (timeFrame != null) timeFrame?.endDate?.short() ?: "--" else "--"
@ -285,11 +285,6 @@ open class Session : RealmObject(), SessionInterface, RowRepresentableDataSource
} }
} }
override var title: String = "Change that: $creationDate"
override val primaryKey: String get() = this.id
override fun getBottomSheetData(row: RowRepresentable): ArrayList<BottomSheetData> { override fun getBottomSheetData(row: RowRepresentable): ArrayList<BottomSheetData> {
val data = ArrayList<BottomSheetData>() val data = ArrayList<BottomSheetData>()

@ -12,7 +12,7 @@ import net.pokeranalytics.android.ui.view.SimpleRow
import net.pokeranalytics.android.ui.view.TournamentFeatureRow import net.pokeranalytics.android.ui.view.TournamentFeatureRow
import java.util.* import java.util.*
open class TournamentFeature : RealmObject(), RowRepresentableDataSource, LiveDataDataSource, RowEditable, ObjectSavable { open class TournamentFeature : RealmObject(), RowRepresentableDataSource, RowEditable, ObjectSavable, RowRepresentable {
@PrimaryKey @PrimaryKey
var id = UUID.randomUUID().toString() var id = UUID.randomUUID().toString()
@ -20,8 +20,13 @@ open class TournamentFeature : RealmObject(), RowRepresentableDataSource, LiveDa
// The name of the feature // The name of the feature
var name: String = "" var name: String = ""
override val title: String get() = this.name override fun getDisplayName(): String {
override val primaryKey: String get() = this.id return this.name
}
override fun uniqueIdentifier(): String {
return this.id
}
override fun adapterRows(): ArrayList<RowRepresentable> { override fun adapterRows(): ArrayList<RowRepresentable> {
val rows = ArrayList<RowRepresentable>() val rows = ArrayList<RowRepresentable>()

@ -13,7 +13,7 @@ import net.pokeranalytics.android.ui.view.TransactionTypeRow
import java.util.* import java.util.*
open class TransactionType : RealmObject(), RowRepresentableDataSource, LiveDataDataSource, RowEditable, ObjectSavable { open class TransactionType : RealmObject(), RowRepresentableDataSource, RowEditable, ObjectSavable, RowRepresentable {
@PrimaryKey @PrimaryKey
var id = UUID.randomUUID().toString() var id = UUID.randomUUID().toString()
@ -30,8 +30,13 @@ open class TransactionType : RealmObject(), RowRepresentableDataSource, LiveData
// The predefined kind, if necessary, like: Withdrawal, deposit, or tips // The predefined kind, if necessary, like: Withdrawal, deposit, or tips
var kind: Int? = null var kind: Int? = null
override val title: String get() = this.name override fun getDisplayName(): String {
override val primaryKey: String get() = this.id return this.name
}
override fun uniqueIdentifier(): String {
return this.id
}
override fun adapterRows(): ArrayList<RowRepresentable> { override fun adapterRows(): ArrayList<RowRepresentable> {
val rows = ArrayList<RowRepresentable>() val rows = ArrayList<RowRepresentable>()

@ -16,7 +16,6 @@ enum class LiveDataViewType {
interface LiveDataDataSource { interface LiveDataDataSource {
val title: String val title: String
val primaryKey: String
} }
interface LiveDataDelegate { interface LiveDataDelegate {

@ -6,18 +6,45 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import net.pokeranalytics.android.ui.view.BindableHolder import net.pokeranalytics.android.ui.view.BindableHolder
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableDiffCallback
import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.RowViewType
interface RowRepresentableDataSource : DisplayableDataSource {
fun rowRepresentableForPosition(position:Int): RowRepresentable {
if (this.numberOfRows() > position) {
return this.adapterRows()[position]
} else {
throw IllegalStateException("Need to implement Data Source")
}
}
fun numberOfRows(): Int {
return this.adapterRows().size
}
fun viewTypeForPosition(position:Int): Int {
return this.rowRepresentableForPosition(position).viewType
}
fun indexForRow(row:RowRepresentable): Int {
return this.adapterRows().indexOf(row)
}
}
interface RowRepresentableDelegate : DisplayableDelegate {
fun onIndexSelected(position: Int) {}
}
/** /**
* An interface used to provide RowRepresentableAdapter content and value in the form of rows * An interface used to provide RowRepresentableAdapter content and value in the form of rows
*/ */
interface RowRepresentableDataSource { interface DisplayableDataSource {
/** /**
* Returns a list of rows * Returns a list of rows
*/ */
fun adapterRows(): ArrayList<RowRepresentable> fun adapterRows(): ArrayList<RowRepresentable> {
return ArrayList()
}
/** /**
* Returns a boolean for a specific row * Returns a boolean for a specific row
@ -48,39 +75,29 @@ interface RowRepresentableDataSource {
* - switch (bool) * - switch (bool)
* - static content * - static content
* */ * */
} }
/** /**
* A delegate used to propagate UI actions * A delegate used to propagate UI actions
*/ */
interface RowRepresentableDelegate { interface DisplayableDelegate {
fun onRowSelected(row: RowRepresentable) {} fun onRowSelected(row: RowRepresentable) {}
fun onActionSelected(row: RowRepresentable) {} fun onActionSelected(row: RowRepresentable) {}
} }
/** /**
* An adapter capable of displaying a list of RowRepresentables * An adapter capable of displaying a list of RowRepresentables
* @param rowRepresentableDataSource the datasource providing rows * @param dataSource the datasource providing rows
* @param rowRepresentableDelegate the delegate, notified of UI actions * @param delegate the delegate, notified of UI actions
*/ */
class RowRepresentableAdapter( class RowRepresentableAdapter(
var rowRepresentableDataSource: RowRepresentableDataSource, var dataSource: RowRepresentableDataSource,
var rowRepresentableDelegate: RowRepresentableDelegate? = null var delegate: RowRepresentableDelegate? = null
) : ) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() { RecyclerView.Adapter<RecyclerView.ViewHolder>() {
/**
* The list of rows to display
*/
private var rows: ArrayList<RowRepresentable> = ArrayList()
init {
this.rows = rowRepresentableDataSource.adapterRows()
}
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {
return this.rows[position].viewType return this.dataSource.viewTypeForPosition(position)
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
@ -89,28 +106,29 @@ class RowRepresentableAdapter(
} }
override fun getItemCount(): Int { override fun getItemCount(): Int {
return this.rows.size return this.dataSource.numberOfRows()
} }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val dynamicRow = this.rows[position] val dynamicRow = this.dataSource.rowRepresentableForPosition(position)
val listener = View.OnClickListener { val listener = View.OnClickListener {
rowRepresentableDelegate?.onRowSelected(dynamicRow) delegate?.onRowSelected(dynamicRow)
delegate?.onIndexSelected(position)
} }
val actionListener = View.OnClickListener { val actionListener = View.OnClickListener {
rowRepresentableDelegate?.onActionSelected(dynamicRow) delegate?.onActionSelected(dynamicRow)
} }
(holder as BindableHolder).bind(dynamicRow, this.rowRepresentableDataSource, listener, actionListener) (holder as BindableHolder).bind(dynamicRow, this.dataSource, listener, actionListener)
} }
/** /**
* Refresh the row in the adapter * Refresh the row in the adapter
*/ */
fun refreshRow(row: RowRepresentable) { fun refreshRow(row: RowRepresentable) {
val index = rows.indexOf(row) val index = this.dataSource.indexForRow(row)
if (index >= 0) { if (index >= 0) {
notifyItemChanged(index) notifyItemChanged(index)
} }
@ -119,9 +137,7 @@ class RowRepresentableAdapter(
/** /**
* Update UI * Update UI
*/ */
fun updateRows(newRows: ArrayList<RowRepresentable>) { fun updateRows(diffResult: DiffUtil.DiffResult) {
val diffResult = DiffUtil.calculateDiff(RowRepresentableDiffCallback(newRows, rows, rowRepresentableDataSource))
this.rows = newRows
diffResult.dispatchUpdatesTo(this) diffResult.dispatchUpdatesTo(this)
} }

@ -5,17 +5,21 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import io.realm.ObjectChangeSet
import io.realm.Realm import io.realm.Realm
import io.realm.RealmResults import io.realm.RealmResults
import kotlinx.android.synthetic.main.fragment_data_list.* import kotlinx.android.synthetic.main.fragment_data_list.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.ObjectSavable
import net.pokeranalytics.android.ui.activity.EditableDataActivity import net.pokeranalytics.android.ui.activity.EditableDataActivity
import net.pokeranalytics.android.ui.adapter.components.* import net.pokeranalytics.android.ui.adapter.components.*
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.SettingRow import net.pokeranalytics.android.ui.view.SettingRow
import timber.log.Timber import timber.log.Timber
class DataListFragment : PokerAnalyticsFragment(), LiveDataDelegate { class DataListFragment : PokerAnalyticsFragment(), RowRepresentableDataSource, RowRepresentableDelegate{
private lateinit var dataType: SettingRow private lateinit var dataType: SettingRow
@ -31,20 +35,28 @@ class DataListFragment : PokerAnalyticsFragment(), LiveDataDelegate {
initUI() initUI()
} }
override fun data(position: Int): LiveDataDataSource { override fun rowRepresentableForPosition(position: Int): RowRepresentable {
return (items[position] as LiveDataDataSource) return this.items[position] as RowRepresentable
} }
override fun onRowSelected(position: Int) { override fun numberOfRows(): Int {
return this.items.size
}
override fun viewTypeForPosition(position: Int): Int {
return RowViewType.DATA.ordinal
}
override fun indexForRow(row: RowRepresentable): Int {
return this.items.indexOf(row)
}
override fun onIndexSelected(position: Int) {
this.dataType.relatedResultsRepresentable?.let { this.dataType.relatedResultsRepresentable?.let {
EditableDataActivity.newInstance(requireContext(), it.ordinal, this.data(position).primaryKey) EditableDataActivity.newInstance(requireContext(), it.ordinal, (this.items[position] as ObjectSavable).uniqueIdentifier())
} }
} }
override fun size(): Int {
return items.size
}
private fun initData() { private fun initData() {
} }
@ -54,7 +66,7 @@ class DataListFragment : PokerAnalyticsFragment(), LiveDataDelegate {
private fun initUI() { private fun initUI() {
val viewManager = LinearLayoutManager(requireContext()) val viewManager = LinearLayoutManager(requireContext())
val dataListAdapter = LiveDataAdapter(this) val dataListAdapter = RowRepresentableAdapter(this, this)
recyclerView.apply { recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)

@ -12,10 +12,7 @@ import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.ObjectSavable import net.pokeranalytics.android.model.ObjectSavable
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.adapter.components.LiveDataDataSource import net.pokeranalytics.android.ui.adapter.components.*
import net.pokeranalytics.android.ui.adapter.components.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.components.RowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.components.RowRepresentableDelegate
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetDelegate import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetDelegate
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment
@ -66,16 +63,16 @@ class EditableDataFragment : PokerAnalyticsFragment(), RowRepresentableDelegate,
override fun clickOnClear(row: RowRepresentable) { override fun clickOnClear(row: RowRepresentable) {
Toast.makeText(requireContext(), "Clear: $row", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), "Clear: $row", Toast.LENGTH_SHORT).show()
(this.item as RowEditable).updateValue(null, row)
this.getRealm().executeTransaction { this.getRealm().executeTransaction {
(this.item as RowEditable).updateValue(null, row)
it.copyToRealmOrUpdate(this.item) it.copyToRealmOrUpdate(this.item)
} }
rowRepresentableAdapter.refreshRow(row) rowRepresentableAdapter.refreshRow(row)
} }
override fun setValue(value: Any?, row: RowRepresentable) { override fun setValue(value: Any?, row: RowRepresentable) {
(this.item as RowEditable).updateValue(value, row)
this.getRealm().executeTransaction { this.getRealm().executeTransaction {
(this.item as RowEditable).updateValue(value, row)
it.copyToRealmOrUpdate(this.item) it.copyToRealmOrUpdate(this.item)
} }
rowRepresentableAdapter.refreshRow(row) rowRepresentableAdapter.refreshRow(row)
@ -141,7 +138,7 @@ class EditableDataFragment : PokerAnalyticsFragment(), RowRepresentableDelegate,
Toast.makeText(requireContext(), "isManaged", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), "isManaged", Toast.LENGTH_SHORT).show()
Timber.d("is managed") Timber.d("is managed")
this.getRealm().executeTransaction { this.getRealm().executeTransaction {
this.liveDataType.deleteData(it, (this.item as LiveDataDataSource)) this.liveDataType.deleteData(it, (this.item as ObjectSavable))
} }
} else { } else {
Toast.makeText(requireContext(), "isNotManaged", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), "isNotManaged", Toast.LENGTH_SHORT).show()

@ -6,6 +6,7 @@ import android.view.animation.OvershootInterpolator
import android.widget.Toast import android.widget.Toast
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.interpolator.view.animation.FastOutSlowInInterpolator import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.recyclerview.widget.DiffUtil
import io.realm.kotlin.where import io.realm.kotlin.where
import kotlinx.android.synthetic.main.fragment_session.* import kotlinx.android.synthetic.main.fragment_session.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
@ -22,6 +23,7 @@ import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetDelegate import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetDelegate
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableDiffCallback
import net.pokeranalytics.android.ui.view.SessionRow import net.pokeranalytics.android.ui.view.SessionRow
import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager
import net.pokeranalytics.android.util.px import net.pokeranalytics.android.util.px
@ -147,7 +149,6 @@ class SessionFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, Bott
floatingActionButton.setOnClickListener { floatingActionButton.setOnClickListener {
manageSessionState() manageSessionState()
} }
} }
/** /**
@ -160,56 +161,89 @@ class SessionFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, Bott
SessionState.PENDING -> { SessionState.PENDING -> {
state.text = "WAITING" state.text = "WAITING"
state.setTextColor(ContextCompat.getColor(requireContext(), R.color.white)) state.setTextColor(ContextCompat.getColor(requireContext(), R.color.white))
sessionData.animate().translationY(-(72f.px)).alpha(0f).setInterpolator(FastOutSlowInInterpolator()).setDuration(500).start()
recyclerView.animate().translationY(-(72f.px)).setInterpolator(FastOutSlowInInterpolator()).setDuration(500).start()
sessionMenu?.findItem(R.id.restart)?.isVisible = false sessionMenu?.findItem(R.id.restart)?.isVisible = false
floatingActionButton.setImageResource(R.drawable.ic_outline_play) floatingActionButton.setImageResource(R.drawable.ic_outline_play)
bottomAppBar.menu.findItem(R.id.stop).isVisible = false bottomAppBar.menu.findItem(R.id.stop).isVisible = false
floatingActionButton.animate().scaleX(1f).scaleY(1f).alpha(1f) floatingActionButton.animate().scaleX(1f).scaleY(1f).alpha(1f)
.setInterpolator(OvershootInterpolator()).start() .setInterpolator(OvershootInterpolator()).start()
sessionData.animate().translationY(-(72f.px)).alpha(1f)
.setInterpolator(FastOutSlowInInterpolator()).setDuration(500).start()
recyclerView.animate().translationY(-(72f.px))
.setInterpolator(FastOutSlowInInterpolator()).setDuration(500).start()
} }
SessionState.STARTED -> { SessionState.STARTED -> {
state.text = "PLAYING" state.text = "PLAYING"
state.setTextColor(ContextCompat.getColor(requireContext(), R.color.green)) state.setTextColor(ContextCompat.getColor(requireContext(), R.color.green))
sessionData.animate().translationY(0f).alpha(1f).setInterpolator(FastOutSlowInInterpolator()).setDuration(500).start()
recyclerView.animate().translationY(0f.px).setInterpolator(FastOutSlowInInterpolator()).setDuration(500).start()
sessionMenu?.findItem(R.id.restart)?.isVisible = true sessionMenu?.findItem(R.id.restart)?.isVisible = true
floatingActionButton.setImageResource(R.drawable.ic_outline_pause) floatingActionButton.setImageResource(R.drawable.ic_outline_pause)
bottomAppBar.menu.findItem(R.id.stop).isVisible = true bottomAppBar.menu.findItem(R.id.stop).isVisible = true
floatingActionButton.animate().scaleX(1f).scaleY(1f).alpha(1f) floatingActionButton.animate().scaleX(1f).scaleY(1f).alpha(1f)
.setInterpolator(OvershootInterpolator()).start() .setInterpolator(OvershootInterpolator()).start()
sessionData.animate().translationY(0f).alpha(1f)
.setInterpolator(FastOutSlowInInterpolator()).setDuration(500).start()
recyclerView.animate().translationY(0f.px)
.setInterpolator(FastOutSlowInInterpolator()).setDuration(500).start()
} }
SessionState.PAUSED -> { SessionState.PAUSED -> {
state.text = "BREAK" state.text = "BREAK"
state.setTextColor(ContextCompat.getColor(requireContext(), R.color.blue)) state.setTextColor(ContextCompat.getColor(requireContext(), R.color.blue))
sessionData.animate().translationY(0f).alpha(1f).setInterpolator(FastOutSlowInInterpolator()).setDuration(500).start()
recyclerView.animate().translationY(0f.px).setInterpolator(FastOutSlowInInterpolator()).setDuration(500).start()
sessionMenu?.findItem(R.id.restart)?.isVisible = true sessionMenu?.findItem(R.id.restart)?.isVisible = true
floatingActionButton.setImageResource(R.drawable.ic_outline_play) floatingActionButton.setImageResource(R.drawable.ic_outline_play)
bottomAppBar.menu.findItem(R.id.stop).isVisible = true bottomAppBar.menu.findItem(R.id.stop).isVisible = true
floatingActionButton.animate().scaleX(1f).scaleY(1f).alpha(1f) floatingActionButton.animate().scaleX(1f).scaleY(1f).alpha(1f)
.setInterpolator(OvershootInterpolator()).start() .setInterpolator(OvershootInterpolator()).start()
sessionData.animate().translationY(0f).alpha(1f)
.setInterpolator(FastOutSlowInInterpolator()).setDuration(500).start()
recyclerView.animate().translationY(0f.px)
.setInterpolator(FastOutSlowInInterpolator()).setDuration(500).start()
} }
SessionState.FINISHED -> { SessionState.FINISHED -> {
state.text = "FINISHED" state.text = "FINISHED"
state.setTextColor(ContextCompat.getColor(requireContext(), R.color.white)) state.setTextColor(ContextCompat.getColor(requireContext(), R.color.white))
sessionData.animate().translationY(0f).alpha(1f).setInterpolator(FastOutSlowInInterpolator()).setDuration(500).start()
recyclerView.animate().translationY(0f.px).setInterpolator(FastOutSlowInInterpolator()).setDuration(500).start()
sessionMenu?.findItem(R.id.restart)?.isVisible = true sessionMenu?.findItem(R.id.restart)?.isVisible = true
bottomAppBar.menu.findItem(R.id.stop).isVisible = false bottomAppBar.menu.findItem(R.id.stop).isVisible = false
floatingActionButton.animate().scaleX(0f).scaleY(0f).alpha(0f) floatingActionButton.animate().scaleX(0f).scaleY(0f).alpha(0f)
.setInterpolator(FastOutSlowInInterpolator()).start() .setInterpolator(FastOutSlowInInterpolator()).start()
sessionData.animate().translationY(0f).alpha(1f)
.setInterpolator(FastOutSlowInInterpolator()).setDuration(500).start()
recyclerView.animate().translationY(0f.px)
.setInterpolator(FastOutSlowInInterpolator()).setDuration(500).start()
} }
} }
sessionAdapter.updateRows(currentSession.adapterRows()) updateAdapterUI(true)
recyclerView.smoothScrollToPosition(0)
} }
/**
* Update adapter UI
*/
private fun updateAdapterUI(scrollToTop: Boolean) {
val diffResult = DiffUtil.calculateDiff(RowRepresentableDiffCallback(currentSession.adapterRows(), oldRows))
sessionAdapter.updateRows(diffResult)
oldRows.clear()
oldRows.addAll(currentSession.adapterRows())
if (scrollToTop) {
recyclerView.smoothScrollToPosition(0)
}
}
val oldRows: ArrayList<RowRepresentable> = ArrayList()
/** /**
* Update the state of the session (start / pause) * Update the state of the session (start / pause)
*/ */
private fun manageSessionState() { private fun manageSessionState() {
Timber.d("oldRows: $oldRows")
when (currentSession.getState()) { when (currentSession.getState()) {
SessionState.PENDING -> { SessionState.PENDING -> {
currentSession.startSession() currentSession.startSession()

@ -8,16 +8,14 @@ import io.realm.RealmResults
import kotlinx.android.synthetic.main.bottom_sheet_list.* import kotlinx.android.synthetic.main.bottom_sheet_list.*
import kotlinx.android.synthetic.main.fragment_bottom_sheet.view.* import kotlinx.android.synthetic.main.fragment_bottom_sheet.view.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.Game import net.pokeranalytics.android.ui.adapter.components.*
import net.pokeranalytics.android.ui.adapter.components.LiveDataAdapter import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.adapter.components.LiveDataDataSource import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.adapter.components.LiveDataDelegate
import net.pokeranalytics.android.ui.adapter.components.LiveDataViewType
class BottomSheetListFragment : BottomSheetFragment(), LiveDataDelegate { class BottomSheetListFragment : BottomSheetFragment(), RowRepresentableDataSource, RowRepresentableDelegate {
private var realmData: RealmResults<*>? = null private var realmData: RealmResults<*>? = null
private lateinit var dataAdapter: LiveDataAdapter private lateinit var dataAdapter: RowRepresentableAdapter
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -30,15 +28,32 @@ class BottomSheetListFragment : BottomSheetFragment(), LiveDataDelegate {
dataAdapter.notifyDataSetChanged() dataAdapter.notifyDataSetChanged()
} }
override fun data(position: Int): LiveDataDataSource { override fun rowRepresentableForPosition(position: Int): RowRepresentable {
realmData?.let { realmData?.let {
return it[position] as LiveDataDataSource return it[position] as RowRepresentable
} }
//TODO: Change that return super.rowRepresentableForPosition(position)
return Game()
} }
override fun onRowSelected(position: Int) { override fun numberOfRows(): Int {
realmData?.let {
return it.size
}
return super.numberOfRows()
}
override fun viewTypeForPosition(position: Int): Int {
return RowViewType.BOTTOM_SHEET_DATA.ordinal
}
override fun indexForRow(row: RowRepresentable): Int {
realmData?.let {
return it.indexOf(row)
}
return super.indexForRow(row)
}
override fun onIndexSelected(position: Int) {
realmData?.let { realmData?.let {
val selectedData = it[position] val selectedData = it[position]
selectedData?.let {data -> selectedData?.let {data ->
@ -46,10 +61,7 @@ class BottomSheetListFragment : BottomSheetFragment(), LiveDataDelegate {
dismiss() dismiss()
} }
} }
} super.onIndexSelected(position)
override fun size(): Int {
return realmData?.size ?: 0
} }
/** /**
@ -70,7 +82,7 @@ class BottomSheetListFragment : BottomSheetFragment(), LiveDataDelegate {
LayoutInflater.from(requireContext()).inflate(R.layout.bottom_sheet_list, view?.bottomSheetContainer, true) LayoutInflater.from(requireContext()).inflate(R.layout.bottom_sheet_list, view?.bottomSheetContainer, true)
val viewManager = LinearLayoutManager(requireContext()) val viewManager = LinearLayoutManager(requireContext())
dataAdapter = LiveDataAdapter(this, LiveDataViewType.BOTTOM_SHEET_DATA) dataAdapter = RowRepresentableAdapter(this, this)
reyclerView.apply { reyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)

@ -8,19 +8,18 @@ import io.realm.RealmResults
import kotlinx.android.synthetic.main.bottom_sheet_game_list.* import kotlinx.android.synthetic.main.bottom_sheet_game_list.*
import kotlinx.android.synthetic.main.fragment_bottom_sheet.view.* import kotlinx.android.synthetic.main.fragment_bottom_sheet.view.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.Game
import net.pokeranalytics.android.ui.adapter.LimitTypesAdapter import net.pokeranalytics.android.ui.adapter.LimitTypesAdapter
import net.pokeranalytics.android.ui.adapter.components.LiveDataAdapter import net.pokeranalytics.android.ui.adapter.components.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.components.LiveDataDataSource import net.pokeranalytics.android.ui.adapter.components.RowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.components.LiveDataDelegate import net.pokeranalytics.android.ui.adapter.components.RowRepresentableDelegate
import net.pokeranalytics.android.ui.adapter.components.LiveDataViewType import net.pokeranalytics.android.ui.view.RowRepresentable
import timber.log.Timber import net.pokeranalytics.android.ui.view.RowViewType
class BottomSheetListGameFragment : BottomSheetFragment(), LiveDataDelegate { class BottomSheetListGameFragment : BottomSheetFragment(), RowRepresentableDataSource, RowRepresentableDelegate {
private var realmData: RealmResults<*>? = null private var realmData: RealmResults<*>? = null
private lateinit var dataAdapter: LiveDataAdapter private lateinit var dataAdapter: RowRepresentableAdapter
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -33,15 +32,33 @@ class BottomSheetListGameFragment : BottomSheetFragment(), LiveDataDelegate {
dataAdapter.notifyDataSetChanged() dataAdapter.notifyDataSetChanged()
} }
override fun data(position: Int): LiveDataDataSource {
override fun rowRepresentableForPosition(position: Int): RowRepresentable {
realmData?.let {
return it[position] as RowRepresentable
}
return super.rowRepresentableForPosition(position)
}
override fun numberOfRows(): Int {
realmData?.let { realmData?.let {
return it[position] as LiveDataDataSource return it.size
} }
//TODO: Change that return super.numberOfRows()
return Game() }
override fun viewTypeForPosition(position: Int): Int {
return RowViewType.BOTTOM_SHEET_DATA.ordinal
} }
override fun onRowSelected(position: Int) { override fun indexForRow(row: RowRepresentable): Int {
realmData?.let {
return it.indexOf(row)
}
return super.indexForRow(row)
}
override fun onIndexSelected(position: Int) {
realmData?.let { realmData?.let {
val selectedData = it[position] val selectedData = it[position]
selectedData?.let {data -> selectedData?.let {data ->
@ -49,13 +66,7 @@ class BottomSheetListGameFragment : BottomSheetFragment(), LiveDataDelegate {
dismiss() dismiss()
} }
} }
} super.onIndexSelected(position)
override fun size(): Int {
Timber.d("Games: ${realmData?.size}")
return realmData?.size ?: 0
} }
/** /**
@ -91,7 +102,7 @@ class BottomSheetListGameFragment : BottomSheetFragment(), LiveDataDelegate {
val viewManager2 = LinearLayoutManager(requireContext()) val viewManager2 = LinearLayoutManager(requireContext())
dataAdapter = LiveDataAdapter(this, LiveDataViewType.BOTTOM_SHEET_DATA) dataAdapter = RowRepresentableAdapter(this, this)
recyclerView2.apply { recyclerView2.apply {
setHasFixedSize(true) setHasFixedSize(true)

@ -29,11 +29,17 @@ interface Localizable {
} }
} }
interface RowRepresentable : Displayable {
fun getDisplayName(): String {
return "UNKNOWN NAME"
}
}
/** /**
* An interface used so that enums values can be represented visually * An interface used so that enums values can be represented visually
* as rows in RecyclerViews * as rows in RecyclerViews
*/ */
interface RowRepresentable : Localizable { interface Displayable: Localizable {
/** /**
* The type of view associated with the row * The type of view associated with the row
*/ */

@ -2,12 +2,8 @@ package net.pokeranalytics.android.ui.view
import androidx.annotation.Nullable import androidx.annotation.Nullable
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import net.pokeranalytics.android.ui.adapter.components.RowRepresentableDataSource
class RowRepresentableDiffCallback( class RowRepresentableDiffCallback(var newRows: List<RowRepresentable>, var oldRows: List<RowRepresentable>) :
var newRows: List<RowRepresentable>, var oldRows: List<RowRepresentable>,
var rowRepresentableDataSource: RowRepresentableDataSource
) :
DiffUtil.Callback() { DiffUtil.Callback() {
override fun getOldListSize(): Int { override fun getOldListSize(): Int {

@ -3,6 +3,8 @@ package net.pokeranalytics.android.ui.view
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.widget.AppCompatTextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.row_header_title_value.view.* import kotlinx.android.synthetic.main.row_header_title_value.view.*
import kotlinx.android.synthetic.main.row_title.view.* import kotlinx.android.synthetic.main.row_title.view.*
@ -26,7 +28,9 @@ enum class RowViewType {
EDIT_TEXT, EDIT_TEXT,
TITLE, TITLE,
TITLE_VALUE, TITLE_VALUE,
TITLE_VALUE_ACTION; TITLE_VALUE_ACTION,
DATA,
BOTTOM_SHEET_DATA;
inner class FakeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), inner class FakeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder { BindableHolder {
@ -34,6 +38,20 @@ enum class RowViewType {
} }
} }
inner class DataViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
override fun bind(row: RowRepresentable, rowRepresentableDataSource: RowRepresentableDataSource?, listener: View.OnClickListener, actionListener: View.OnClickListener?) {
itemView.findViewById<AppCompatTextView>(R.id.rowTitle_title).text = row.getDisplayName()
itemView.findViewById<ConstraintLayout>(R.id.rowTitle_container).setOnClickListener(listener)
}
}
inner class BottomSheetDataViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
override fun bind(row: RowRepresentable, rowRepresentableDataSource: RowRepresentableDataSource?, listener: View.OnClickListener, actionListener: View.OnClickListener?) {
itemView.findViewById<AppCompatTextView>(R.id.title).text = row.getDisplayName()
itemView.findViewById<ConstraintLayout>(R.id.container).setOnClickListener(listener)
}
}
inner class TitleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), inner class TitleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder { BindableHolder {
override fun bind(row: RowRepresentable, rowRepresentableDataSource: RowRepresentableDataSource?, listener: View.OnClickListener, actionListener: View.OnClickListener?) { override fun bind(row: RowRepresentable, rowRepresentableDataSource: RowRepresentableDataSource?, listener: View.OnClickListener, actionListener: View.OnClickListener?) {
@ -115,7 +133,20 @@ enum class RowViewType {
false false
) )
) )
DATA -> DataViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_title,
parent,
false
)
)
BOTTOM_SHEET_DATA -> BottomSheetDataViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_bottom_sheet_title,
parent,
false
)
)
else -> FakeViewHolder(parent) else -> FakeViewHolder(parent)
} }
} }

Loading…
Cancel
Save