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

# Conflicts:
#	app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt
#	app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt
#	app/src/main/java/net/pokeranalytics/android/ui/fragment/data/EditableDataFragment.kt
#	app/src/main/java/net/pokeranalytics/android/ui/fragment/report/AbstractReportFragment.kt
#	app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ComparisonReportFragment.kt
#	app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ProgressReportFragment.kt
#	app/src/main/java/net/pokeranalytics/android/ui/fragment/report/TableReportFragment.kt
#	app/src/main/res/layout/fragment_reports.xml
dev
Aurelien Hubert 7 years ago
commit 885671be31
  1. 63
      app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt
  2. 96
      app/src/main/java/net/pokeranalytics/android/model/LiveData.kt
  3. 5
      app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt
  4. 20
      app/src/main/java/net/pokeranalytics/android/model/realm/ReportSetup.kt
  5. 14
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  6. 39
      app/src/main/java/net/pokeranalytics/android/ui/activity/ComparisonReportActivity.kt
  7. 5
      app/src/main/java/net/pokeranalytics/android/ui/activity/EditableDataActivity.kt
  8. 26
      app/src/main/java/net/pokeranalytics/android/ui/activity/ProgressReportActivity.kt
  9. 36
      app/src/main/java/net/pokeranalytics/android/ui/activity/TableReportActivity.kt
  10. 39
      app/src/main/java/net/pokeranalytics/android/ui/activity/components/ReportActivity.kt
  11. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDetailsFragment.kt
  12. 35
      app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt
  13. 10
      app/src/main/java/net/pokeranalytics/android/ui/fragment/CalendarDetailsFragment.kt
  14. 60
      app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt
  15. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt
  16. 49
      app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt
  17. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/SessionFragment.kt
  18. 54
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt
  19. 46
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt
  20. 4
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetMultiSelectionFragment.kt
  21. 4
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/BankrollDataFragment.kt
  22. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/CustomFieldDataFragment.kt
  23. 158
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/DataManagerFragment.kt
  24. 172
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/EditableDataFragment.kt
  25. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/LocationDataFragment.kt
  26. 8
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/TransactionDataFragment.kt
  27. 115
      app/src/main/java/net/pokeranalytics/android/ui/fragment/report/AbstractReportFragment.kt
  28. 14
      app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ComparisonReportFragment.kt
  29. 8
      app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ComposableTableReportFragment.kt
  30. 15
      app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ProgressReportFragment.kt
  31. 9
      app/src/main/java/net/pokeranalytics/android/ui/fragment/report/TableReportFragment.kt
  32. 71
      app/src/main/java/net/pokeranalytics/android/util/RealmExtensions.kt
  33. 21
      app/src/main/res/layout/dialog_edit_text.xml
  34. 2
      app/src/main/res/layout/fragment_bankroll.xml
  35. 2
      app/src/main/res/layout/fragment_data_list.xml
  36. 1
      app/src/main/res/layout/fragment_reports.xml
  37. 1
      app/src/main/res/layout/fragment_subscription.xml
  38. 1
      app/src/main/res/values/strings.xml

@ -11,8 +11,10 @@ import net.pokeranalytics.android.model.filter.Query
import net.pokeranalytics.android.model.filter.filter
import net.pokeranalytics.android.model.realm.ComputableResult
import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.model.realm.ReportSetup
import net.pokeranalytics.android.model.realm.SessionSet
import net.pokeranalytics.android.ui.activity.ComparisonReportActivity
import net.pokeranalytics.android.ui.activity.ProgressReportActivity
import net.pokeranalytics.android.ui.activity.TableReportActivity
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.util.extensions.startOfDay
import java.util.*
@ -35,7 +37,8 @@ class Calculator {
query: Query = Query(),
filter: Filter? = null,
var aggregationType: AggregationType? = null,
var userGenerated: Boolean = false
var userGenerated: Boolean = false,
var reportSetupId: String? = null
) {
var evolutionValues: EvolutionValues = evolutionValues
@ -47,17 +50,17 @@ class Calculator {
}
private var _query: Query = query
private var _filter: Filter? = filter
var filter: Filter? = filter
init {
if (!this._query.conditions.isEmpty() && this._filter != null) {
if (!this._query.conditions.isEmpty() && this.filter != null) {
throw IllegalStateException("Can't specify a query with conditions AND a filter")
}
}
val query: Query
get() {
this._filter?.let {
this.filter?.let {
return it.query
}
return this._query
@ -84,6 +87,19 @@ class Calculator {
}
}
val activityClass: Class<*>
get() {
return when (this) {
TABLE -> TableReportActivity::class.java
PROGRESS -> ProgressReportActivity::class.java
COMPARISON -> ComparisonReportActivity::class.java
else -> throw IllegalStateException("undefined activity for report display")
// MAP -> R.string.map
// POLYNOMIAL -> null
}
}
}
/**
@ -134,21 +150,21 @@ class Calculator {
}
}
fun reportSetup(name: String): ReportSetup {
val rs = ReportSetup()
rs.name = name
rs.display = this.display.ordinal
this.stats.forEach {
rs.statIds.add(it.uniqueIdentifier)
}
this.criterias.forEach {
rs.criteriaIds.add(it.uniqueIdentifier)
}
rs.filter = this._filter
return rs
}
// fun reportSetup(name: String): ReportSetup {
//
// val rs = ReportSetup()
// rs.name = name
// rs.display = this.display.ordinal
// this.stats.forEach {
// rs.statIds.add(it.uniqueIdentifier)
// }
// this.criterias.forEach {
// rs.criteriaIds.add(it.uniqueIdentifier)
// }
// rs.filter = this.filter
//
// return rs
// }
/**
* Returns some default name
@ -172,8 +188,11 @@ class Calculator {
stats: List<Stat>? = null
): Report {
val options = Options(evolutionValues = Options.EvolutionValues.STANDARD, aggregationType = aggregationType)
options.stats = listOf(stat)
val options = Options(display = Options.Display.PROGRESS,
evolutionValues = Options.EvolutionValues.STANDARD,
stats = listOf(stat),
aggregationType = aggregationType)
if (aggregationType == AggregationType.DURATION) {
options.evolutionValues = Options.EvolutionValues.TIMED
}

@ -2,13 +2,9 @@ package net.pokeranalytics.android.model
import android.content.Context
import io.realm.Realm
import io.realm.RealmObject
import io.realm.RealmResults
import io.realm.Sort
import io.realm.kotlin.where
import io.realm.RealmModel
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.interfaces.CountableUsage
import net.pokeranalytics.android.model.interfaces.Deletable
import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.model.realm.*
import net.pokeranalytics.android.ui.view.Localizable
@ -24,76 +20,10 @@ enum class LiveData : Localizable {
TRANSACTION,
TRANSACTION_TYPE,
FILTER,
CUSTOM_FIELD;
CUSTOM_FIELD,
REPORT_SETUP;
fun items(realm: Realm, fieldName: String? = null, sortOrder: Sort? = null): RealmResults<*> {
val results = realm.where(this.relatedEntity).findAll().sort(fieldName ?: this.sortingFieldName, sortOrder ?: this.sorting)
if (results.size > 0) {
if (results.first() is CountableUsage) {
this.setUseCount(realm, results)
return results.sort("useCount", Sort.DESCENDING)
}
}
return results
}
fun setUseCount(realm: Realm, realmResults: RealmResults<*>) {
realm.executeTransaction {
realmResults.forEach { countableUsage ->
when (this) {
TOURNAMENT_FEATURE -> {
(countableUsage as CountableUsage).useCount = it.where<Session>().contains(
"tournamentFeatures.id",
countableUsage.id
).count().toInt()
}
else -> {
(countableUsage as CountableUsage).useCount = it.where<Session>().equalTo(
"${relatedEntity.simpleName.decapitalize()}.id",
countableUsage.id
).count().toInt()
}
}
}
}
}
/**
* Return a copy of a RealmResults
*/
fun itemsArray(realm: Realm, fieldName: String? = null, sortOrder: Sort? = null): ArrayList<*> {
val results: ArrayList<Any> = ArrayList()
results.addAll(
realm.copyFromRealm(
realm.where(this.relatedEntity).findAll().sort(
fieldName ?: this.sortingFieldName, sortOrder ?: this.sorting
)
)
)
return results
}
private val sortingFieldName: String
get() {
return when (this) {
TRANSACTION -> "date"
else -> "name"
}
}
private val sorting: Sort
get() {
return when (this) {
TRANSACTION -> Sort.DESCENDING
else -> Sort.ASCENDING
}
}
private val relatedEntity: Class<out RealmObject>
val relatedEntity: Class<out Identifiable>
get() {
return when (this) {
BANKROLL -> Bankroll::class.java
@ -105,15 +35,12 @@ enum class LiveData : Localizable {
TRANSACTION_TYPE -> TransactionType::class.java
FILTER -> Filter::class.java
CUSTOM_FIELD -> CustomField::class.java
REPORT_SETUP -> ReportSetup::class.java
}
}
fun deleteData(realm: Realm, data: Deletable) {
realm.where(this.relatedEntity).equalTo("id", data.id).findAll().deleteAllFromRealm()
}
fun updateOrCreate(realm: Realm, primaryKey: String?): RealmObject {
val proxyItem: RealmObject? = this.getData(realm, primaryKey)
fun updateOrCreate(realm: Realm, primaryKey: String?): RealmModel {
val proxyItem: Identifiable? = this.getData(realm, primaryKey)
proxyItem?.let {
return realm.copyFromRealm(it)
} ?: run {
@ -121,12 +48,12 @@ enum class LiveData : Localizable {
}
}
fun newEntity(): RealmObject {
private fun newEntity(): RealmModel{
return this.relatedEntity.newInstance()
}
fun getData(realm: Realm, primaryKey: String?): RealmObject? {
var proxyItem: RealmObject? = null
fun getData(realm: Realm, primaryKey: String?): Identifiable? {
var proxyItem: Identifiable? = null
primaryKey?.let {
val t = realm.where(this.relatedEntity).equalTo("id", it).findFirst()
t?.let {
@ -148,6 +75,7 @@ enum class LiveData : Localizable {
TRANSACTION_TYPE -> R.string.operation_types
FILTER -> R.string.filter
CUSTOM_FIELD -> R.string.custom_fields
REPORT_SETUP -> R.string.custom
}
}

@ -7,6 +7,7 @@ import io.realm.kotlin.where
import net.pokeranalytics.android.model.filter.Filterable
import net.pokeranalytics.android.model.filter.Query
import net.pokeranalytics.android.model.filter.QueryCondition
import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.ui.interfaces.FilterableType
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow
@ -17,7 +18,7 @@ import java.util.*
* It contains a list of [FilterCondition] describing the complete query to launch
* The [Filter] is working closely with a [Filterable] interface providing the entity we want the query being launched on
*/
open class Filter : RealmObject(), RowRepresentable {
open class Filter : RealmObject(), RowRepresentable, Identifiable {
companion object {
@ -49,7 +50,7 @@ open class Filter : RealmObject(), RowRepresentable {
}
@PrimaryKey
var id = UUID.randomUUID().toString()
override var id = UUID.randomUUID().toString()
// the queryWith name
var name: String = ""

@ -1,6 +1,7 @@
package net.pokeranalytics.android.model.realm
import android.content.Context
import io.realm.Realm
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.Ignore
@ -8,15 +9,17 @@ import io.realm.annotations.PrimaryKey
import net.pokeranalytics.android.calculus.Calculator
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.model.Criteria
import net.pokeranalytics.android.model.interfaces.Deletable
import net.pokeranalytics.android.model.interfaces.DeleteValidityStatus
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import java.util.*
open class ReportSetup : RealmObject(), RowRepresentable {
open class ReportSetup : RealmObject(), RowRepresentable, Deletable {
@PrimaryKey
var id = UUID.randomUUID().toString()
override var id = UUID.randomUUID().toString()
// The name of the report
var name: String = ""
@ -60,8 +63,19 @@ open class ReportSetup : RealmObject(), RowRepresentable {
stats = stats,
criterias = criteria,
filter = this.filter,
userGenerated = true
userGenerated = true,
reportSetupId = this.id
)
}
// Deletable
override fun isValidForDelete(realm: Realm): Boolean {
return true
}
override fun getFailedDeleteMessage(status: DeleteValidityStatus): Int {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}

@ -18,7 +18,6 @@ import net.pokeranalytics.android.calculus.StatFormattingException
import net.pokeranalytics.android.calculus.TextFormat
import net.pokeranalytics.android.exceptions.ModelException
import net.pokeranalytics.android.model.Limit
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.TableSize
import net.pokeranalytics.android.model.TournamentType
import net.pokeranalytics.android.model.extensions.SessionState
@ -39,6 +38,7 @@ import net.pokeranalytics.android.ui.view.rowrepresentable.SessionRow
import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.UserDefaults
import net.pokeranalytics.android.util.extensions.*
import net.pokeranalytics.android.util.sorted
import java.text.DateFormat
import java.util.*
import java.util.Currency
@ -697,7 +697,7 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat
// Add custom fields
realm?.let {
rows.add(SeparatorRow())
rows.addAll(LiveData.CUSTOM_FIELD.itemsArray(it) as ArrayList<RowRepresentable>)
rows.addAll(it.sorted<CustomField>())
}
return rows
@ -778,32 +778,32 @@ open class Session : RealmObject(), Savable, Editable, StaticRowRepresentableDat
SessionRow.BANKROLL -> row.editingDescriptors(
mapOf(
"defaultValue" to this.bankroll,
"data" to LiveData.BANKROLL.items(realm)
"data" to realm.sorted<Bankroll>() // LiveData.BANKROLL.items(realm)
)
)
SessionRow.GAME -> row.editingDescriptors(
mapOf(
"limit" to this.limit,
"defaultValue" to this.game,
"data" to LiveData.GAME.items(realm)
"data" to realm.sorted<Game>() //LiveData.GAME.items(realm)
)
)
SessionRow.LOCATION -> row.editingDescriptors(
mapOf(
"defaultValue" to this.location,
"data" to LiveData.LOCATION.items(realm)
"data" to realm.sorted<Location>() // LiveData.LOCATION.items(realm)
)
)
SessionRow.TOURNAMENT_FEATURE -> row.editingDescriptors(
mapOf(
"defaultValue" to this.tournamentFeatures,
"data" to LiveData.TOURNAMENT_FEATURE.items(realm)
"data" to realm.sorted<TournamentFeature>() //LiveData.TOURNAMENT_FEATURE.items(realm)
)
)
SessionRow.TOURNAMENT_NAME -> row.editingDescriptors(
mapOf(
"defaultValue" to this.tournamentName,
"data" to LiveData.TOURNAMENT_NAME.items(realm)
"data" to realm.sorted<TournamentName>() //LiveData.TOURNAMENT_NAME.items(realm)
)
)
SessionRow.TOURNAMENT_TYPE -> row.editingDescriptors(

@ -1,35 +1,12 @@
package net.pokeranalytics.android.ui.activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Report
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.activity.components.ReportActivity
import net.pokeranalytics.android.ui.fragment.report.ComparisonReportFragment
class ComparisonReportActivity : PokerAnalyticsActivity() {
companion object {
// Unparcel fails when setting a custom Parcelable object on Entry so we use a static reference to passe objects
private var report: Report? = null
private var reportTitle: String = ""
/**
* Default constructor
*/
fun newInstance(context: Context, report: Report, reportTitle: String) {
//parameters = GraphParameters(stat, group, report)
this.report = report
this.reportTitle = reportTitle
val intent = Intent(context, ComparisonReportActivity::class.java)
context.startActivity(intent)
}
}
class ComparisonReportActivity : ReportActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -42,14 +19,18 @@ class ComparisonReportActivity : PokerAnalyticsActivity() {
*/
private fun initUI() {
report?.let {
parameters?.let {
val report = it.report
val title = it.title
val fragmentTransaction = supportFragmentManager.beginTransaction()
val reportDetailsFragment = ComparisonReportFragment.newInstance(it, reportTitle)
val reportDetailsFragment = ComparisonReportFragment.newInstance(report, title)
fragmentTransaction.add(R.id.reportDetailsContainer, reportDetailsFragment)
fragmentTransaction.commit()
report = null
}
parameters = null
}
}

@ -10,6 +10,7 @@ import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.fragment.data.*
class EditableDataActivity : PokerAnalyticsActivity() {
enum class IntentKey(val keyName: String) {
DATA_TYPE("DATA_TYPE"),
PRIMARY_KEY("PRIMARY_KEY");
@ -31,9 +32,9 @@ class EditableDataActivity : PokerAnalyticsActivity() {
/**
* Create a new instance for result
*/
fun newInstanceForResult(fragment: Fragment, dataType: Int, primaryKey: String? = null, requestCode: Int) {
fun newInstanceForResult(fragment: Fragment, dataType: LiveData, primaryKey: String? = null, requestCode: Int) {
val intent = Intent(fragment.requireContext(), EditableDataActivity::class.java)
intent.putExtra(IntentKey.DATA_TYPE.keyName, dataType)
intent.putExtra(IntentKey.DATA_TYPE.keyName, dataType.ordinal)
primaryKey?.let {
intent.putExtra(IntentKey.PRIMARY_KEY.keyName, it)
}

@ -3,33 +3,35 @@ package net.pokeranalytics.android.ui.activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Report
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.activity.components.ReportActivity
import net.pokeranalytics.android.ui.activity.components.ReportParameters
import net.pokeranalytics.android.ui.fragment.report.ProgressReportFragment
class StatisticsDetailsParameters(var stat: Stat, var report: Report, var title: String? = null)
class ProgressReportActivity : PokerAnalyticsActivity() {
class ProgressReportActivity : ReportActivity() {
companion object {
// Unparcel fails when setting a custom Parcelable object on Entry so we use a static reference to passe objects
private var parameters: StatisticsDetailsParameters? = null
private var displayAggregationChoices: Boolean = true
/**
* Default constructor
*/
fun newInstance(context: Context, stat: Stat, report: Report, displayAggregationChoices: Boolean = true, title: String? = null) {
parameters = StatisticsDetailsParameters(stat, report, title)
this.displayAggregationChoices = displayAggregationChoices
fun newInstance(context: Context, report: Report, title: String, stat: Stat? = null, displayAggregationChoices: Boolean = true) {
parameters = ReportParameters(report, title, stat, showAggregationChoices = displayAggregationChoices)
val intent = Intent(context, ProgressReportActivity::class.java)
context.startActivity(intent)
}
fun newInstanceForResult(fragment: Fragment, report: Report, title: String, stat: Stat? = null, displayAggregationChoices: Boolean = true) {
parameters = ReportParameters(report, title, stat, showAggregationChoices = displayAggregationChoices)
val intent = Intent(fragment.context, ProgressReportActivity::class.java)
fragment.startActivityForResult(intent, DEFAULT_REQUEST_CODE)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
@ -49,7 +51,9 @@ class ProgressReportActivity : PokerAnalyticsActivity() {
fragmentTransaction.commit()
parameters?.let {
statisticDetailsFragment.setData(it.stat, it.report, displayAggregationChoices, it.title)
val report = it.report
val stat = it.stat ?: report.options.stats.first()
statisticDetailsFragment.setData(report, stat, it.showAggregationChoices, it.title)
parameters = null
}

@ -1,32 +1,11 @@
package net.pokeranalytics.android.ui.activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Report
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.activity.components.ReportActivity
import net.pokeranalytics.android.ui.fragment.report.TableReportFragment
class TableReportActivity : PokerAnalyticsActivity() {
companion object {
// Unparcel fails when setting a custom Parcelable object on Entry so we use a static reference to passe objects
private var report: Report? = null
private var reportTitle: String = ""
/**
* Default constructor
*/
fun newInstance(context: Context, report: Report, reportTitle: String) {
this.report = report
this.reportTitle = reportTitle
val intent = Intent(context, TableReportActivity::class.java)
context.startActivity(intent)
}
}
class TableReportActivity : ReportActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -39,11 +18,18 @@ class TableReportActivity : PokerAnalyticsActivity() {
*/
private fun initUI() {
parameters?.let {
val report = it.report
val title = it.title
val fragmentTransaction = supportFragmentManager.beginTransaction()
val fragment = TableReportFragment.newInstance(report, reportTitle)
val fragment = TableReportFragment.newInstance(report, title)
fragmentTransaction.add(R.id.reportDetailsContainer, fragment)
fragmentTransaction.commit()
report = null
}
parameters = null
}
}

@ -0,0 +1,39 @@
package net.pokeranalytics.android.ui.activity.components
import android.content.Context
import android.content.Intent
import androidx.fragment.app.Fragment
import net.pokeranalytics.android.calculus.Report
import net.pokeranalytics.android.calculus.Stat
class ReportParameters(var report: Report, var title: String, var stat: Stat? = null, var showAggregationChoices: Boolean = true)
abstract class ReportActivity : PokerAnalyticsActivity() {
companion object {
const val DEFAULT_REQUEST_CODE = 999
// Unparcel fails when setting a custom Parcelable object on Entry so we use a static reference to passe objects
var parameters: ReportParameters? = null
/**
* Default constructor
*/
fun newInstance(context: Context, report: Report, reportTitle: String, stat: Stat? = null) {
val options = report.options
this.parameters = ReportParameters(report, reportTitle, stat)
val intent = Intent(context, options.display.activityClass)
context.startActivity(intent)
}
fun newInstanceForResult(fragment: Fragment, report: Report, reportTitle: String, stat: Stat? = null) {
val options = report.options
this.parameters = ReportParameters(report, reportTitle, stat)
val intent = Intent(fragment.requireContext(), options.display.activityClass)
fragment.startActivityForResult(intent, DEFAULT_REQUEST_CODE)
}
}
}

@ -161,7 +161,7 @@ class BankrollDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentable
* Open Bankroll edit activity
*/
private fun editBankroll() {
EditableDataActivity.newInstanceForResult(this, LiveData.BANKROLL.ordinal, bankrollReport.setup.bankroll?.id, REQUEST_CODE_EDIT)
EditableDataActivity.newInstanceForResult(this, LiveData.BANKROLL, bankrollReport.setup.bankroll?.id, REQUEST_CODE_EDIT)
}
}

@ -28,6 +28,7 @@ import net.pokeranalytics.android.ui.activity.BankrollDetailsActivity
import net.pokeranalytics.android.ui.activity.DataListActivity
import net.pokeranalytics.android.ui.activity.EditableDataActivity
import net.pokeranalytics.android.ui.activity.GraphActivity
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
@ -36,6 +37,8 @@ import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
import net.pokeranalytics.android.ui.view.rowrepresentable.GraphRow
import net.pokeranalytics.android.util.sorted
import net.pokeranalytics.android.util.sorted
import timber.log.Timber
import java.util.*
import kotlin.collections.ArrayList
@ -66,6 +69,12 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
private var lastItemClickedId: String = ""
private var deletedRow: RowRepresentable? = null
private lateinit var bankrolls: RealmResults<Bankroll>
override fun deletableItems() : List<Identifiable> {
return this.bankrolls
}
// Life Cycle
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
@ -83,13 +92,14 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE_DETAILS && resultCode == Activity.RESULT_OK) {
val needToDeleteItem = data?.getBooleanExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName, false) ?: false
if (needToDeleteItem) {
val itemToDeleteId = data?.getStringExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName)
itemToDeleteId?.let { id ->
GlobalScope.launch(Dispatchers.Main) {
delay(300)
deleteItem(bankrollAdapter, LiveData.BANKROLL.items(getRealm()), lastItemClickedId)
deleteItem(dataListAdapter, bankrolls, id)
}
}
} else if (requestCode == REQUEST_CODE_CREATE && resultCode == Activity.RESULT_OK) {
//TODO: Refresh bankrolls
initData()
@ -126,6 +136,9 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
*/
private fun initData() {
val realm = getRealm()
this.bankrolls = realm.sorted()
rows.clear()
bankrollReportForRow.clear()
@ -150,7 +163,7 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
Timber.d("initData: ${System.currentTimeMillis() - startDate.time}ms")
val bankrolls = LiveData.BANKROLL.items(getRealm()) as RealmResults<Bankroll>
// val bankrolls = LiveData.BANKROLL.items(getRealm()) as RealmResults<Bankroll>
bankrolls.forEach { bankroll ->
val bankrollReportSetup = BankrollReportSetup(bankroll)
@ -165,7 +178,7 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
}
if (!isDetached) {
bankrollAdapter.notifyDataSetChanged()
dataListAdapter.notifyDataSetChanged()
}
}
}
@ -179,20 +192,18 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
setDisplayHomeAsUpEnabled(true)
bankrollAdapter = RowRepresentableAdapter(this, this)
dataListAdapter = RowRepresentableAdapter(this, this)
val viewManager = LinearLayoutManager(requireContext())
recyclerView.apply {
setHasFixedSize(true)
layoutManager = viewManager
adapter = bankrollAdapter
adapter = dataListAdapter
}
addButton.setOnClickListener {
LiveData.BANKROLL?.let {
EditableDataActivity.newInstanceForResult(this@BankrollFragment, dataType = it.ordinal, primaryKey = null, requestCode = REQUEST_CODE_CREATE)
}
EditableDataActivity.newInstanceForResult(this@BankrollFragment, dataType = LiveData.BANKROLL, primaryKey = null, requestCode = REQUEST_CODE_CREATE)
}
}
@ -200,7 +211,7 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
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)
dataListAdapter.notifyItemRemoved(lastItemClickedPosition)
}
override fun updateUIAfterUndoDeletion(newItem: RealmObject) {
@ -214,7 +225,7 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
bankrollReportForRow[row] = bankrollReport
rows.add(lastItemClickedPosition, row)
bankrollAdapter.notifyItemInserted(lastItemClickedPosition)
dataListAdapter.notifyItemInserted(lastItemClickedPosition)
}
}

@ -137,10 +137,12 @@ class CalendarDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentable
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
when (row) {
is GraphRow -> {
row.report?.let { report ->
row.stat?.let { stat ->
ProgressReportActivity.newInstance(requireContext(), stat, report, false, row.title)
}
val report = row.report
val stat = row.stat
if (report != null && stat != null) {
val title = row.title ?: stat.localizedTitle(requireContext())
ProgressReportActivity.newInstance(requireContext(), report, title, stat, false)
}
}
}

@ -10,15 +10,10 @@ import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import io.realm.RealmResults
import kotlinx.android.synthetic.main.fragment_data_list.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.ui.activity.DataListActivity
import net.pokeranalytics.android.ui.activity.EditableDataActivity
import net.pokeranalytics.android.ui.activity.FiltersActivity
import net.pokeranalytics.android.ui.adapter.LiveRowRepresentableDataSource
@ -28,6 +23,8 @@ import net.pokeranalytics.android.ui.fragment.components.DeletableItemFragment
import net.pokeranalytics.android.ui.helpers.SwipeToDeleteCallback
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.util.sorted
class DataListFragment : DeletableItemFragment(), LiveRowRepresentableDataSource, RowRepresentableDelegate {
@ -35,20 +32,27 @@ class DataListFragment : DeletableItemFragment(), LiveRowRepresentableDataSource
const val REQUEST_CODE_DETAILS = 1000
}
private lateinit var identifiableClass: Class<out Identifiable>
private lateinit var dataType: LiveData
private lateinit var items: RealmResults<*>
private lateinit var dataListAdapter: RowRepresentableAdapter
private var lastItemClickedId: String = ""
private lateinit var items: RealmResults<out Identifiable>
override fun deletableItems() : List<Identifiable> {
return this.items
}
/**
* Set fragment data
*/
fun setData(dataType: Int) {
this.dataType = LiveData.values()[dataType]
this.identifiableClass = this.dataType.relatedEntity
setToolbarTitle(this.dataType.localizedTitle(requireContext()))
this.dataType.let {
this.items = it.items(getRealm())
}
val realm = getRealm()
this.items = realm.sorted(this.identifiableClass)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
@ -61,7 +65,6 @@ class DataListFragment : DeletableItemFragment(), LiveRowRepresentableDataSource
initUI()
}
/**
* Init UI
*/
@ -87,29 +90,13 @@ class DataListFragment : DeletableItemFragment(), LiveRowRepresentableDataSource
}
this.addButton.setOnClickListener {
this.dataType?.let {
EditableDataActivity.newInstance(
requireContext(),
dataType = it.ordinal,
dataType = this.dataType.ordinal,
primaryKey = null
)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE_DETAILS && resultCode == Activity.RESULT_OK) {
val needToDeleteItem =
data?.getBooleanExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName, false) ?: false
if (needToDeleteItem) {
GlobalScope.launch(Dispatchers.Main) {
delay(300)
deleteItem(dataListAdapter, items, lastItemClickedId)
}
}
}
}
override fun onResume() {
super.onResume()
@ -130,21 +117,24 @@ class DataListFragment : DeletableItemFragment(), LiveRowRepresentableDataSource
}
override fun indexForRow(row: RowRepresentable): Int {
return this.items.indexOf(row)
return this.items.indexOf(row as Identifiable)
}
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
this.dataType?.let {
if (it == LiveData.FILTER) {
when (this.dataType) {
LiveData.FILTER -> {
val intent = Intent()
intent.putExtra(FiltersActivity.IntentKey.FILTER_ID.keyName, (row as Filter).id)
activity?.setResult(Activity.RESULT_OK, intent)
activity?.finish()
} else {
lastItemClickedId = (row as Identifiable).id
EditableDataActivity.newInstanceForResult(this, it.ordinal, lastItemClickedId, REQUEST_CODE_DETAILS)
}
else -> {
val identifier = (row as Identifiable).id
EditableDataActivity.newInstanceForResult(this, this.dataType, identifier, REQUEST_CODE_DETAILS)
}
}
}
}

@ -105,7 +105,7 @@ class FeedFragment : RealmFragment(), RowRepresentableDelegate {
is Transaction -> {
selectedTransaction = row
selectedTransactionPosition = position
EditableDataActivity.newInstanceForResult(this, LiveData.TRANSACTION.ordinal, row.id, REQUEST_CODE_TRANSACTION_DETAILS)
EditableDataActivity.newInstanceForResult(this, LiveData.TRANSACTION, row.id, REQUEST_CODE_TRANSACTION_DETAILS)
}
}
}

@ -13,21 +13,22 @@ import io.realm.RealmResults
import kotlinx.android.synthetic.main.fragment_data_list.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Calculator
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.model.Criteria
import net.pokeranalytics.android.model.combined
import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.model.realm.ReportSetup
import net.pokeranalytics.android.ui.activity.ComparisonReportActivity
import net.pokeranalytics.android.ui.activity.ProgressReportActivity
import net.pokeranalytics.android.ui.activity.DataListActivity
import net.pokeranalytics.android.ui.activity.ReportCreationActivity
import net.pokeranalytics.android.ui.activity.TableReportActivity
import net.pokeranalytics.android.ui.activity.components.ReportActivity
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.fragment.components.RealmFragment
import net.pokeranalytics.android.ui.fragment.components.DeletableItemFragment
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
@ -35,12 +36,16 @@ import net.pokeranalytics.android.ui.view.rowrepresentable.ReportRow
import timber.log.Timber
import java.util.*
class ReportsFragment : RealmFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate {
class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate {
private lateinit var reportsAdapter: RowRepresentableAdapter
// private lateinit var dataListAdapter: RowRepresentableAdapter
private lateinit var reportSetups: RealmResults<ReportSetup>
private var adapterRows = mutableListOf<RowRepresentable>()
override fun deletableItems(): List<Identifiable> {
return this.reportSetups
}
companion object {
/**
@ -77,9 +82,17 @@ class ReportsFragment : RealmFragment(), StaticRowRepresentableDataSource, RowRe
this.launchReportWithOptions(options, options.getName(requireContext()))
}
ReportCreationActivity.options = null
} else if (requestCode == ReportActivity.DEFAULT_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
val itemToDeleteId = data?.getStringExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName)
itemToDeleteId?.let { id ->
GlobalScope.launch(Dispatchers.Main) {
delay(300)
deleteItem(dataListAdapter, reportSetups, id)
}
}
}
}
// Business
@ -98,14 +111,14 @@ class ReportsFragment : RealmFragment(), StaticRowRepresentableDataSource, RowRe
*/
private fun initUI() {
reportsAdapter = RowRepresentableAdapter(this, this)
dataListAdapter = RowRepresentableAdapter(this, this)
val viewManager = LinearLayoutManager(requireContext())
recyclerView.apply {
setHasFixedSize(true)
layoutManager = viewManager
adapter = reportsAdapter
adapter = dataListAdapter
}
this.addButton.setOnClickListener {
@ -116,14 +129,14 @@ class ReportsFragment : RealmFragment(), StaticRowRepresentableDataSource, RowRe
// Rows
fun updateRows() {
private fun updateRows() {
this.adapterRows.clear()
if (this.reportSetups.size > 0) {
adapterRows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.custom))
adapterRows.addAll(this.reportSetups)
}
adapterRows.addAll(ReportRow.getRows())
this.reportsAdapter.notifyDataSetChanged()
this.dataListAdapter.notifyDataSetChanged()
}
override fun adapterRows(): List<RowRepresentable>? {
@ -185,21 +198,7 @@ class ReportsFragment : RealmFragment(), StaticRowRepresentableDataSource, RowRe
launch(Dispatchers.Main) {
if (!isDetached) {
hideLoader()
when (options.display) {
Calculator.Options.Display.TABLE -> {
TableReportActivity.newInstance(requireContext(), report, reportName)
}
Calculator.Options.Display.PROGRESS -> {
ProgressReportActivity.newInstance(requireContext(), options.stats.first(), report)
}
Calculator.Options.Display.COMPARISON -> {
ComparisonReportActivity.newInstance(requireContext(), report, reportName)
}
else -> {
Timber.d("Report type not handled at the moment")
}
}
ReportActivity.newInstanceForResult(this@ReportsFragment, report, reportName)
}
}
realm.close()

@ -289,7 +289,7 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate {
* Add new custom field
*/
private fun addNewCustomField() {
EditableDataActivity.newInstanceForResult(this, LiveData.CUSTOM_FIELD.ordinal, requestCode = REQUEST_CODE_NEW_CUSTOM_FIELD)
EditableDataActivity.newInstanceForResult(this, LiveData.CUSTOM_FIELD, requestCode = REQUEST_CODE_NEW_CUSTOM_FIELD)
}
/**

@ -1,32 +1,47 @@
package net.pokeranalytics.android.ui.fragment.components
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.google.android.material.snackbar.Snackbar
import io.realm.RealmObject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.interfaces.Deletable
import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.ui.activity.DataListActivity
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
/**
* 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() {
abstract class DeletableItemFragment : RealmFragment() {
companion object {
const val REQUEST_CODE_DELETION = 1000
}
lateinit var dataListAdapter: RowRepresentableAdapter
private var deletedItem: RealmObject? = null
private var itemHasBeenReInserted: Boolean = false
private var lastDeletedItemPosition: Int = 0
private var dataListAdapter: RowRepresentableAdapter? = null
private var coordinatorLayout: CoordinatorLayout? = null
private var mainLayout: ViewGroup? = null
private var snackBar: Snackbar? = null
abstract fun deletableItems() : List<Identifiable>
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
this.coordinatorLayout = view.findViewById(R.id.coordinatorLayout)
this.mainLayout = view.findViewById(R.id.mainLayout)
}
override fun onPause() {
@ -34,6 +49,21 @@ open class DeletableItemFragment : RealmFragment() {
snackBar?.dismiss()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE_DELETION && resultCode == Activity.RESULT_OK) {
val itemToDeleteId = data?.getStringExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName)
itemToDeleteId?.let { id ->
GlobalScope.launch(Dispatchers.Main) {
delay(300)
deleteItem(dataListAdapter, deletableItems(), id)
}
}
}
}
/**
* Delete item
* [dataListAdapter]: Adapter to update
@ -41,7 +71,7 @@ open class DeletableItemFragment : RealmFragment() {
* [itemId]: Id of the item to delete
* [container]: View to display the Snackbar
*/
fun deleteItem(dataListAdapter: RowRepresentableAdapter, items: List<*>, itemId: String) {
fun deleteItem(dataListAdapter: RowRepresentableAdapter, items: List<Identifiable>, itemId: String) {
if (isDetached || activity == null) {
return
@ -50,8 +80,8 @@ open class DeletableItemFragment : RealmFragment() {
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 }
val itemPosition = items.indexOfFirst { it.id == itemId }
val itemToDelete = items.find { it.id == itemId }
if (itemToDelete is RealmObject && itemPosition != -1) {
@ -85,7 +115,7 @@ open class DeletableItemFragment : RealmFragment() {
*/
private fun showUndoSnackBar() {
val message = String.format(getString(R.string.data_deleted))
this.coordinatorLayout?.let { view ->
this.mainLayout?.let { view ->
snackBar = Snackbar.make(view, message, Snackbar.LENGTH_INDEFINITE)
snackBar?.setAction(R.string.cancel) {
if (!itemHasBeenReInserted) {
@ -99,6 +129,8 @@ open class DeletableItemFragment : RealmFragment() {
}
}
snackBar?.show()
} ?: run {
throw IllegalStateException("mainLayout is not defined")
}
}
@ -106,14 +138,14 @@ open class DeletableItemFragment : RealmFragment() {
* Called once the object has been deleted
*/
open fun updateUIAfterDeletion(itemPosition: Int) {
dataListAdapter?.notifyItemRemoved(itemPosition)
dataListAdapter.notifyItemRemoved(itemPosition)
}
/**
* Called once the object has been restored
*/
open fun updateUIAfterUndoDeletion(newItem: RealmObject) {
dataListAdapter?.notifyItemInserted(lastDeletedItemPosition)
dataListAdapter.notifyItemInserted(lastDeletedItemPosition)
}
}

@ -12,7 +12,7 @@ import android.view.WindowManager
import androidx.appcompat.view.ContextThemeWrapper
import androidx.fragment.app.FragmentManager
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import io.realm.RealmObject
import io.realm.RealmModel
import kotlinx.android.synthetic.main.fragment_bottom_sheet.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.LiveData
@ -82,7 +82,7 @@ open class BottomSheetFragment : BottomSheetDialogFragment() {
val primaryKey = data.getStringExtra(EditableDataActivity.IntentKey.PRIMARY_KEY.keyName)
val pokerAnalyticsActivity = activity as PokerAnalyticsActivity
val liveDataType = LiveData.values()[dataType]
val proxyItem: RealmObject? = liveDataType.getData(pokerAnalyticsActivity.getRealm(), primaryKey)
val proxyItem: RealmModel? = liveDataType.getData(pokerAnalyticsActivity.getRealm(), primaryKey)
this.delegate.onRowValueChanged(proxyItem, this.row)
dismiss()
}
@ -122,38 +122,22 @@ open class BottomSheetFragment : BottomSheetDialogFragment() {
}
bottomSheetToolbar.menu.findItem(R.id.actionAdd).setOnMenuItemClickListener {
when (row) {
SessionRow.GAME -> EditableDataActivity.newInstanceForResult(
this,
LiveData.GAME.ordinal,
requestCode = REQUEST_CODE_ADD_NEW_OBJECT
)
SessionRow.BANKROLL, TransactionRow.BANKROLL -> EditableDataActivity.newInstanceForResult(
this,
LiveData.BANKROLL.ordinal,
requestCode = REQUEST_CODE_ADD_NEW_OBJECT
)
SessionRow.LOCATION -> EditableDataActivity.newInstanceForResult(
this,
LiveData.LOCATION.ordinal,
requestCode = REQUEST_CODE_ADD_NEW_OBJECT
)
SessionRow.TOURNAMENT_NAME -> EditableDataActivity.newInstanceForResult(
this,
LiveData.TOURNAMENT_NAME.ordinal,
requestCode = REQUEST_CODE_ADD_NEW_OBJECT
)
SessionRow.TOURNAMENT_FEATURE -> EditableDataActivity.newInstanceForResult(
this,
LiveData.TOURNAMENT_FEATURE.ordinal,
requestCode = REQUEST_CODE_ADD_NEW_OBJECT
)
TransactionRow.TYPE -> EditableDataActivity.newInstanceForResult(
val liveData = when (row) {
SessionRow.GAME -> LiveData.GAME
SessionRow.BANKROLL, TransactionRow.BANKROLL -> LiveData.BANKROLL
SessionRow.LOCATION -> LiveData.LOCATION
SessionRow.TOURNAMENT_NAME -> LiveData.TOURNAMENT_NAME
SessionRow.TOURNAMENT_FEATURE -> LiveData.TOURNAMENT_FEATURE
TransactionRow.TYPE -> LiveData.TRANSACTION_TYPE
else -> throw IllegalStateException("row $row does not have an associated LiveData value")
}
EditableDataActivity.newInstanceForResult(
this,
LiveData.TRANSACTION_TYPE.ordinal,
liveData,
requestCode = REQUEST_CODE_ADD_NEW_OBJECT
)
}
true
}
bottomSheetToolbar.menu.findItem(R.id.actionCheck).setOnMenuItemClickListener {

@ -3,7 +3,7 @@ package net.pokeranalytics.android.ui.fragment.components.bottomsheet
import android.app.Activity
import android.content.Intent
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.RealmModel
import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorException
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.ui.activity.EditableDataActivity
@ -28,7 +28,7 @@ open class BottomSheetMultiSelectionFragment : BottomSheetListFragment() {
val primaryKey = data.getStringExtra(EditableDataActivity.IntentKey.PRIMARY_KEY.keyName)
val pokerAnalyticsActivity = activity as PokerAnalyticsActivity
val liveDataType = LiveData.values()[dataType]
val proxyItem: RealmObject? = liveDataType.getData(pokerAnalyticsActivity.getRealm(), primaryKey)
val proxyItem: RealmModel? = liveDataType.getData(pokerAnalyticsActivity.getRealm(), primaryKey)
selectedRows.add(proxyItem as RowRepresentable)
dataAdapter.refreshRow(proxyItem as RowRepresentable)
}

@ -157,11 +157,11 @@ class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataS
/**
* Init data
*/
private fun initData() {
override fun initData() {
defaultCurrency = UserDefaults.currency
if (!isUpdating) {
if (!deleteButtonShouldAppear) {
bankroll.currency = net.pokeranalytics.android.model.realm.Currency()
bankroll.currency?.code = defaultCurrency.currencyCode
bankroll.currency?.rate = 1.0

@ -258,7 +258,7 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
updateUI()
rowRepresentableAdapter.notifyDataSetChanged()
if (!isUpdating) {
if (!this.deleteButtonShouldAppear) {
rowRepresentableForPosition(0)?.let {
onRowSelected(0, it)
}

@ -0,0 +1,158 @@
package net.pokeranalytics.android.ui.fragment.data
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.appcompat.app.AlertDialog
import io.realm.RealmModel
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.ConfigurationException
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.interfaces.Deletable
import net.pokeranalytics.android.model.interfaces.Savable
import net.pokeranalytics.android.model.interfaces.SaveValidityStatus
import net.pokeranalytics.android.ui.activity.DataListActivity
import net.pokeranalytics.android.ui.activity.EditableDataActivity
import net.pokeranalytics.android.ui.fragment.components.RealmFragment
open class DataManagerFragment : RealmFragment() {
lateinit var item: RealmModel
lateinit var liveDataType: LiveData
protected var primaryKey: String? = null
var deleteButtonShouldAppear = false
set(value) {
field = value
this.updateMenuUI()
}
var saveButtonShouldAppear = true
set(value) {
field = value
this.updateMenuUI()
}
protected var dataType: Int? = null
private var editableMenu: Menu? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initData()
}
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
menu?.clear()
inflater?.inflate(R.menu.toolbar_editable_data, menu)
this.editableMenu = menu
updateMenuUI()
super.onCreateOptionsMenu(menu, inflater)
}
/**
* Update menu UI
*/
private fun updateMenuUI() {
editableMenu?.findItem(R.id.delete)?.isVisible = this.deleteButtonShouldAppear
editableMenu?.findItem(R.id.save)?.isVisible = this.saveButtonShouldAppear
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item!!.itemId) {
R.id.save -> saveData()
R.id.delete -> deleteData()
}
return true
}
/**
* Init data
*/
protected open fun initData() {
this.deleteButtonShouldAppear = this.primaryKey != null
this.item = this.liveDataType.updateOrCreate(this.getRealm(), primaryKey)
}
/**
* Save data
*/
protected open fun saveData() {
val savable = this.item
when (savable) {
is Savable -> {
val status = savable.getSaveValidityStatus(realm = this.getRealm())
when (status) {
SaveValidityStatus.VALID -> {
this.getRealm().executeTransaction {
val managedItem = it.copyToRealmOrUpdate(this.item)
if (managedItem is Savable) {
val uniqueIdentifier = (managedItem as Savable).id
finishActivityWithResult(uniqueIdentifier)
}
}
onDataSaved()
}
else -> {
val message = savable.getFailedSaveMessage(status)
val builder = AlertDialog.Builder(requireContext())
.setMessage(message)
.setNegativeButton(R.string.ok, null)
builder.show()
}
}
}
else -> {
throw ConfigurationException("Save action called on un-Savable object")
}
}
}
/**
* Delete data
*/
protected open fun deleteData() {
val deletable = this.item as Deletable
val realm = this.getRealm()
if (deletable.isValidForDelete(realm)) {
val intent = Intent()
intent.putExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName, deletable.id)
activity?.setResult(Activity.RESULT_OK, intent)
activity?.finish()
} else {
val status = deletable.getDeleteStatus(realm)
val message = deletable.getFailedDeleteMessage(status)
val builder = AlertDialog.Builder(requireContext())
.setMessage(message)
.setNegativeButton(R.string.ok, null)
builder.show()
}
}
/**
* Finish the activity with a result
*/
private fun finishActivityWithResult(uniqueIdentifier: String) {
val intent = Intent()
intent.putExtra(EditableDataActivity.IntentKey.DATA_TYPE.keyName, dataType)
intent.putExtra(EditableDataActivity.IntentKey.PRIMARY_KEY.keyName, uniqueIdentifier)
activity?.setResult(Activity.RESULT_OK, intent)
activity?.finish()
}
open fun onDataSaved() {}
}

@ -1,41 +1,28 @@
package net.pokeranalytics.android.ui.fragment.data
import android.app.Activity.RESULT_OK
import android.content.Intent
import android.os.Bundle
import android.view.*
import androidx.appcompat.app.AlertDialog
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import io.realm.RealmObject
import io.realm.RealmModel
import kotlinx.android.synthetic.main.fragment_editable_data.*
import kotlinx.android.synthetic.main.fragment_editable_data.view.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.ConfigurationException
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.interfaces.Deletable
import net.pokeranalytics.android.model.interfaces.Editable
import net.pokeranalytics.android.model.interfaces.Savable
import net.pokeranalytics.android.model.interfaces.SaveValidityStatus
import net.pokeranalytics.android.ui.activity.DataListActivity
import net.pokeranalytics.android.ui.activity.EditableDataActivity
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.fragment.components.RealmFragment
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment
import net.pokeranalytics.android.ui.view.RowRepresentable
open class EditableDataFragment : RealmFragment(), RowRepresentableDelegate {
open class EditableDataFragment : DataManagerFragment(), RowRepresentableDelegate {
lateinit var item: RealmObject
lateinit var liveDataType: LiveData
lateinit var rowRepresentableAdapter: RowRepresentableAdapter
private var editableMenu: Menu? = null
private var dataType: Int? = null
private var primaryKey: String? = null
var isUpdating = false
var shouldOpenKeyboard = true
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
@ -46,24 +33,15 @@ open class EditableDataFragment : RealmFragment(), RowRepresentableDelegate {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initUI()
initData()
}
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
menu?.clear()
inflater?.inflate(R.menu.toolbar_editable_data, menu)
this.editableMenu = menu
updateMenuUI()
super.onCreateOptionsMenu(menu, inflater)
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item!!.itemId) {
R.id.save -> saveData()
R.id.delete -> deleteData()
}
return true
/**
* Set fragment data
*/
fun setData(dataType: Int, primaryKey: String?) {
this.dataType = dataType
this.liveDataType = LiveData.values()[dataType]
this.primaryKey = primaryKey
}
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
@ -85,6 +63,16 @@ open class EditableDataFragment : RealmFragment(), RowRepresentableDelegate {
setDisplayHomeAsUpEnabled(true)
val proxyItem: RealmModel? = this.liveDataType.getData(this.getRealm(), primaryKey)
proxyItem?.let {
//TODO: Localize
this.appBar.toolbar.title = "Update ${this.liveDataType.localizedTitle(requireContext()).toLowerCase().capitalize()}"
deleteButtonShouldAppear = true
} ?: run {
//TODO: Localize
this.appBar.toolbar.title = this.liveDataType.newEntityLocalizedTitle(requireContext())
}
val viewManager = LinearLayoutManager(requireContext())
recyclerView.apply {
setHasFixedSize(true)
@ -99,126 +87,20 @@ open class EditableDataFragment : RealmFragment(), RowRepresentableDelegate {
return this.item as RowRepresentableDataSource
}
/**
* Init data
*/
private fun initData() {
if (this.dataType != null) {
val proxyItem: RealmObject? = this.liveDataType.getData(this.getRealm(), primaryKey)
proxyItem?.let {
//TODO: Localize
//this.appBar.toolbar.title = "Update ${this.liveDataType.localizedTitle(requireContext()).toLowerCase().capitalize()}"
setToolbarTitle("Update ${this.liveDataType.localizedTitle(requireContext()).toLowerCase().capitalize()}")
isUpdating = true
} ?: run {
//TODO: Localize
//this.appBar.toolbar.title = this.liveDataType.newEntityLocalizedTitle(requireContext())
setToolbarTitle(this.liveDataType.newEntityLocalizedTitle(requireContext()))
}
this.item = this.liveDataType.updateOrCreate(this.getRealm(), primaryKey)
override fun initData() {
super.initData()
val dataSource = getDataSource()
this.rowRepresentableAdapter = RowRepresentableAdapter(getDataSource(), this)
this.rowRepresentableAdapter.setHasStableIds(true)
this.recyclerView.adapter = rowRepresentableAdapter
// When creating an object, open automatically the keyboard for the first row
if (!isUpdating && shouldOpenKeyboard) {
if (!deleteButtonShouldAppear && shouldOpenKeyboard) {
val row = dataSource.adapterRows()?.firstOrNull()
row?.let {
onRowSelected(0, it)
}
}
}
}
/**
* Update menu UI
*/
private fun updateMenuUI() {
editableMenu?.findItem(R.id.delete)?.isVisible = isUpdating
editableMenu?.findItem(R.id.save)?.isVisible = true
}
/**
* Save data
*/
fun saveData() {
val savable = this.item
when (savable) {
is Savable -> {
val status = savable.getSaveValidityStatus(realm = this.getRealm())
when (status) {
SaveValidityStatus.VALID -> {
this.getRealm().executeTransaction {
val managedItem = it.copyToRealmOrUpdate(this.item)
if (managedItem is Savable) {
val uniqueIdentifier = (managedItem as Savable).id
finishActivityWithResult(uniqueIdentifier)
}
}
onDataSaved()
}
else -> {
val message = savable.getFailedSaveMessage(status)
val builder = AlertDialog.Builder(requireContext())
.setMessage(message)
.setNegativeButton(R.string.ok, null)
builder.show()
}
}
} else -> {
throw ConfigurationException("Save action called on un-Savable object")
}
}
}
/**
* Delete data
*/
private fun deleteData() {
val deletable = this.item as Deletable
val realm = this.getRealm()
if (deletable.isValidForDelete(realm)) {
val intent = Intent()
intent.putExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName, true)
activity?.setResult(RESULT_OK, intent)
activity?.finish()
} else {
val status = deletable.getDeleteStatus(realm)
val message = deletable.getFailedDeleteMessage(status)
val builder = AlertDialog.Builder(requireContext())
.setMessage(message)
.setNegativeButton(R.string.ok, null)
builder.show()
}
}
/**
* Finish the activity with a result
*/
private fun finishActivityWithResult(uniqueIdentifier: String) {
val intent = Intent()
intent.putExtra(EditableDataActivity.IntentKey.DATA_TYPE.keyName, dataType)
intent.putExtra(EditableDataActivity.IntentKey.PRIMARY_KEY.keyName, uniqueIdentifier)
activity?.setResult(RESULT_OK, intent)
activity?.finish()
}
/**
* Set fragment data
*/
fun setData(dataType: Int, primaryKey: String?) {
this.dataType = dataType
this.liveDataType = LiveData.values()[dataType]
this.primaryKey = primaryKey
}
open fun onDataSaved() {}
}

@ -40,7 +40,7 @@ class LocationDataFragment : EditableDataFragment(), StaticRowRepresentableDataS
shouldOpenKeyboard = false
locationActivated = parentActivity?.hasLocationPermissionGranted() ?: false
if (isUpdating) {
if (deleteButtonShouldAppear) {
// If we update a location, we set the switch to the correct value
locationActivated = location.latitude != null && location.longitude != null

@ -6,8 +6,9 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.realm.Bankroll
import net.pokeranalytics.android.model.realm.Transaction
import net.pokeranalytics.android.model.realm.TransactionType
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.helpers.DateTimePickerManager
@ -17,6 +18,7 @@ import net.pokeranalytics.android.ui.view.rowrepresentable.TransactionRow
import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.extensions.round
import net.pokeranalytics.android.util.extensions.shortDate
import net.pokeranalytics.android.util.sorted
import java.util.*
/**
@ -56,8 +58,8 @@ class TransactionDataFragment : EditableDataFragment(), StaticRowRepresentableDa
override fun editDescriptors(row: RowRepresentable): ArrayList<RowRepresentableEditDescriptor>? {
return when (row) {
TransactionRow.BANKROLL -> row.editingDescriptors(mapOf("defaultValue" to this.transaction.bankroll, "data" to LiveData.BANKROLL.items(getRealm())))
TransactionRow.TYPE -> row.editingDescriptors(mapOf("defaultValue" to this.transaction.type, "data" to LiveData.TRANSACTION_TYPE.items(getRealm())))
TransactionRow.BANKROLL -> row.editingDescriptors(mapOf("defaultValue" to this.transaction.bankroll, "data" to getRealm().sorted<Bankroll>() ))
TransactionRow.TYPE -> row.editingDescriptors(mapOf("defaultValue" to this.transaction.type, "data" to getRealm().sorted<TransactionType>() ))
TransactionRow.AMOUNT -> row.editingDescriptors(mapOf("defaultValue" to (if (this.transaction.amount != 0.0) this.transaction.amount.round() else "")))
TransactionRow.COMMENT -> row.editingDescriptors(mapOf("defaultValue" to this.transaction.comment))
else -> super.editDescriptors(row)

@ -1,53 +1,110 @@
package net.pokeranalytics.android.ui.fragment.report
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.os.Bundle
import android.view.View
import android.widget.EditText
import androidx.appcompat.app.AlertDialog
import kotlinx.android.synthetic.main.fragment_progress_report.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Report
import net.pokeranalytics.android.ui.fragment.components.RealmFragment
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.realm.ReportSetup
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.fragment.data.DataManagerFragment
abstract class AbstractReportFragment : RealmFragment() {
abstract class AbstractReportFragment : DataManagerFragment() {
protected lateinit var selectedReport: Report
private lateinit var _selectedReport: Report
val selectedReport: Report
get() {
return this._selectedReport
}
fun setReport(report: Report) {
this._selectedReport = report
this.primaryKey = report.options.reportSetupId
}
protected var reportTitle: String? = null
private var editableMenu: Menu? = null
protected lateinit var parentActivity: PokerAnalyticsActivity
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
menu?.clear()
inflater?.inflate(R.menu.toolbar_report, menu)
this.editableMenu = menu
updateMenuUI()
super.onCreateOptionsMenu(menu, inflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item!!.itemId) {
R.id.save -> this.saveReportRequest()
this.liveDataType = LiveData.REPORT_SETUP
this.saveButtonShouldAppear = this._selectedReport.options.userGenerated
this.deleteButtonShouldAppear = (this.primaryKey != null)
}
return true
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
parentActivity = activity as PokerAnalyticsActivity
// Avoid a bug during setting the titleResId
toolbar.title = ""
parentActivity.setSupportActionBar(toolbar)
parentActivity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
setHasOptionsMenu(true)
toolbar.title = reportTitle
}
/**
* Update menu UI
*/
private fun updateMenuUI() {
editableMenu?.findItem(R.id.save)?.let {
it.isVisible = this.selectedReport.options.userGenerated
it.icon.setTint(requireContext().getColor(R.color.white))
override fun saveData() {
activity?.let {
val builder = AlertDialog.Builder(it)
// Get the layout inflater
val inflater = requireActivity().layoutInflater;
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
val view = inflater.inflate(R.layout.dialog_edit_text, null)
val nameEditText = view.findViewById<EditText>(R.id.reportName)
builder.setView(view)
// Add action buttons
.setPositiveButton(R.string.save) { dialog, id ->
saveReport(nameEditText.text.toString())
dialog.dismiss()
}
.setNegativeButton(R.string.cancel) { dialog, id ->
dialog.cancel()
}
private fun saveReportRequest() {
val dialog = builder.create()
dialog.show()
} ?: throw IllegalStateException("Activity cannot be null")
}
private fun saveReport(name: String) {
getRealm().executeTransaction {
val report = this.selectedReport.options.reportSetup(name)
it.insert(report)
getRealm().executeTransaction { realm ->
val rs = this.item as ReportSetup
val options = this._selectedReport.options
rs.name = name
rs.display = options.display.ordinal
options.stats.forEach {
rs.statIds.add(it.uniqueIdentifier)
}
options.criterias.forEach {
rs.criteriaIds.add(it.uniqueIdentifier)
}
rs.filter = options.filter
this.item = rs
this.deleteButtonShouldAppear = true
toolbar.title = name
realm.copyToRealmOrUpdate(rs)
}
}
}

@ -13,28 +13,22 @@ import net.pokeranalytics.android.ui.adapter.ReportPagerAdapter
class ComparisonReportFragment : AbstractReportFragment() {
companion object {
fun newInstance(report: Report?, reportTitle: String): ComparisonReportFragment {
fun newInstance(report: Report, reportTitle: String): ComparisonReportFragment {
val fragment = ComparisonReportFragment()
fragment.reportTitle = reportTitle
report?.let {
fragment.selectedReport = it
}
fragment.setReport(report)
val bundle = Bundle()
fragment.arguments = bundle
return fragment
}
}
// private var reports: MutableMap<AggregationType, Report> = hashMapOf()
// private var stat: Stat = Stat.NET_RESULT
// private var displayAggregationChoices: Boolean = true
/**
* Set data
*/
fun setData(report: Report) {
this.selectedReport = report
this.setReport(report)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

@ -12,7 +12,7 @@ import kotlinx.coroutines.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.*
import net.pokeranalytics.android.model.realm.ComputableResult
import net.pokeranalytics.android.ui.activity.ProgressReportActivity
import net.pokeranalytics.android.ui.activity.components.ReportActivity
import net.pokeranalytics.android.ui.adapter.DisplayDescriptor
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
@ -212,7 +212,11 @@ open class ComposableTableReportFragment : RealmFragment(), StaticRowRepresentab
if (!isDetached) {
hideLoader()
report?.let {
ProgressReportActivity.newInstance(requireContext(), stat, it)
val title = stat.localizedTitle(requireContext())
ReportActivity.newInstance(requireContext(), it, title, stat)
// ProgressReportActivity.newInstance(requireContext(), stat, it, title = title)
}
}
}

@ -64,9 +64,9 @@ class ProgressReportFragment : AbstractReportFragment() {
/**
* Set data
*/
fun setData(stat: Stat, report: Report, displayAggregationChoices: Boolean, title: String? = null) {
fun setData(report: Report, stat: Stat, displayAggregationChoices: Boolean, title: String) {
this.stat = stat
this.selectedReport = report
this.setReport(report)
this.displayAggregationChoices = displayAggregationChoices
this.reportTitle = title
@ -80,15 +80,12 @@ class ProgressReportFragment : AbstractReportFragment() {
*/
private fun initUI() {
setDisplayHomeAsUpEnabled(true)
setToolbarTitle(this.reportTitle ?: stat.localizedTitle(requireContext()))
val fragmentManager = parentActivity?.supportFragmentManager
val fragmentTransaction = fragmentManager?.beginTransaction()
val fragmentManager = parentActivity.supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
graphFragment = GraphFragment()
fragmentTransaction?.add(R.id.graphContainer, graphFragment)
fragmentTransaction?.commit()
fragmentTransaction.add(R.id.graphContainer, graphFragment)
fragmentTransaction.commit()
stat.aggregationTypes.firstOrNull()?.let { aggregationType ->
reports[aggregationType]?.let { report ->

@ -13,15 +13,10 @@ class TableReportFragment : AbstractReportFragment() {
companion object {
/**
* Create new instance
*/
fun newInstance(report: Report? = null, title: String? = null): TableReportFragment {
fun newInstance(report: Report, title: String): TableReportFragment {
val fragment = TableReportFragment()
fragment.reportTitle = title
report?.let {
fragment.selectedReport = it
}
fragment.setReport(report)
val bundle = Bundle()
fragment.arguments = bundle
return fragment

@ -0,0 +1,71 @@
package net.pokeranalytics.android.util
import io.realm.Realm
import io.realm.RealmModel
import io.realm.RealmResults
import io.realm.Sort
import io.realm.kotlin.where
import net.pokeranalytics.android.model.interfaces.CountableUsage
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.TournamentFeature
import net.pokeranalytics.android.model.realm.Transaction
/**
* Returns all entities of the [clazz] sorted with their default sorting
*/
fun <T : RealmModel> Realm.sorted(clazz: Class<T>) : RealmResults<T> {
if (clazz is CountableUsage) {
this.updateUsageCount(clazz)
}
val sortField = when (clazz) {
is CountableUsage -> "useCount"
is Transaction -> "date"
else -> "name"
}
val resultSort = when (clazz) {
is CountableUsage -> Sort.DESCENDING
is Transaction -> Sort.DESCENDING
else -> Sort.ASCENDING
}
return this.where(clazz).findAll().sort(sortField, resultSort)
}
/**
* Returns all entities of the [clazz] sorted with their default sorting
*/
inline fun <reified C : RealmModel> Realm.sorted() : RealmResults<C> {
return this.sorted(C::class.java)
}
/**
* Updates the useCount variable of the CountableUsage entity
*/
fun <T : RealmModel>Realm.updateUsageCount(clazz: Class<T>) {
val results = this.where(clazz).findAll()
this.executeTransaction {
results.forEach { countableUsage ->
val countable = (countableUsage as CountableUsage)
when (clazz) {
is TournamentFeature -> {
countable.useCount = it.where<Session>().contains(
"tournamentFeatures.id",
countable.id
).count().toInt()
}
else -> {
countable.useCount = it.where<Session>().equalTo(
"${clazz.simpleName.decapitalize()}.id",
countable.id
).count().toInt()
}
}
}
}
}

@ -0,0 +1,21 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="24dp">
<androidx.appcompat.widget.AppCompatTextView
android:text="@string/save_report"
style="@style/PokerAnalyticsTheme.TextView.Title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/reportName"
style="@style/PokerAnalyticsTheme.EditText"
android:layout_width="240dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:hint="@string/name" />
</LinearLayout>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinatorLayout"
android:id="@+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">

@ -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/coordinatorLayout"
android:id="@+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">

@ -39,6 +39,7 @@
<androidx.viewpager.widget.ViewPager
android:id="@+id/pager"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"

@ -30,6 +30,7 @@
<string name="new_report_step_filter">Select a filter or launch report</string>
<string name="launch_report">Launch Report</string>
<string name="progress">Progress</string>
<string name="save_report">Save Report</string>
<string name="address">Address</string>
<string name="suggestions">Naming suggestions</string>

Loading…
Cancel
Save