Compare commits

...

17 Commits
master ... kmm

  1. 6
      app/build.gradle
  2. 84
      app/src/main/java/net/pokeranalytics/android/calcul/ComputedResultsExtensions.kt
  3. 64
      app/src/main/java/net/pokeranalytics/android/calcul/ReportExtensions.kt
  4. 7
      app/src/main/java/net/pokeranalytics/android/calculus/AggregationType.kt
  5. 90
      app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt
  6. 239
      app/src/main/java/net/pokeranalytics/android/calculus/Report.kt
  7. 10
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  8. 9
      app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt
  9. 48
      app/src/main/java/net/pokeranalytics/android/ui/activity/ColorPickerActivity.kt
  10. 12
      app/src/main/java/net/pokeranalytics/android/ui/activity/GDPRActivity.kt
  11. 17
      app/src/main/java/net/pokeranalytics/android/ui/activity/GraphActivity.kt
  12. 15
      app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt
  13. 5
      app/src/main/java/net/pokeranalytics/android/ui/adapter/ComparisonChartPagerAdapter.kt
  14. 7
      app/src/main/java/net/pokeranalytics/android/ui/adapter/ReportPagerAdapter.kt
  15. 4
      app/src/main/java/net/pokeranalytics/android/ui/extensions/UIExtensions.kt
  16. 17
      app/src/main/java/net/pokeranalytics/android/ui/fragment/ComparisonChartFragment.kt
  17. 20
      app/src/main/java/net/pokeranalytics/android/ui/fragment/CurrenciesFragment.kt
  18. 55
      app/src/main/java/net/pokeranalytics/android/ui/fragment/GraphFragment.kt
  19. 49
      app/src/main/java/net/pokeranalytics/android/ui/fragment/ImportFragment.kt
  20. 33
      app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportCreationFragment.kt
  21. 24
      app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt
  22. 28
      app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt
  23. 21
      app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt
  24. 55
      app/src/main/java/net/pokeranalytics/android/ui/fragment/SubscriptionFragment.kt
  25. 27
      app/src/main/java/net/pokeranalytics/android/ui/fragment/Top10Fragment.kt
  26. 33
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/FilterableFragment.kt
  27. 22
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/LoaderDialogFragment.kt
  28. 27
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/ScreenSlidePageFragment.kt
  29. 59
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetDoubleEditTextFragment.kt
  30. 26
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetEditTextFragment.kt
  31. 22
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetEditTextMultiLinesFragment.kt
  32. 24
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt
  33. 22
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListFragment.kt
  34. 23
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListGameFragment.kt
  35. 17
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetMultiSelectionFragment.kt
  36. 23
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetNumericTextFragment.kt
  37. 24
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetStaticListFragment.kt
  38. 29
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetSumFragment.kt
  39. 24
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetTableSizeGridFragment.kt
  40. 25
      app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ComparisonReportFragment.kt
  41. 51
      app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ComposableTableReportFragment.kt
  42. 48
      app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ProgressReportFragment.kt
  43. 24
      app/src/main/java/net/pokeranalytics/android/ui/fragment/report/TableReportFragment.kt
  44. 7
      app/src/main/java/net/pokeranalytics/android/ui/graph/GraphExtensions.kt
  45. 16
      app/src/main/java/net/pokeranalytics/android/ui/graph/GraphUnderlyingEntry.kt
  46. 18
      app/src/main/java/net/pokeranalytics/android/ui/modules/bankroll/BankrollDetailsFragment.kt
  47. 18
      app/src/main/java/net/pokeranalytics/android/ui/modules/bankroll/BankrollFragment.kt
  48. 48
      app/src/main/java/net/pokeranalytics/android/ui/modules/calendar/CalendarDetailsFragment.kt
  49. 70
      app/src/main/java/net/pokeranalytics/android/ui/modules/calendar/CalendarFragment.kt
  50. 41
      app/src/main/java/net/pokeranalytics/android/ui/modules/data/CustomFieldDataFragment.kt
  51. 16
      app/src/main/java/net/pokeranalytics/android/ui/modules/data/EditableDataFragment.kt
  52. 17
      app/src/main/java/net/pokeranalytics/android/ui/modules/data/PlayerDataFragment.kt
  53. 21
      app/src/main/java/net/pokeranalytics/android/ui/modules/datalist/DataListFragment.kt
  54. 51
      app/src/main/java/net/pokeranalytics/android/ui/modules/feed/FeedFragment.kt
  55. 10
      app/src/main/java/net/pokeranalytics/android/ui/modules/feed/FeedSessionRowRepresentableAdapter.kt
  56. 7
      app/src/main/java/net/pokeranalytics/android/ui/modules/feed/FeedTransactionRowRepresentableAdapter.kt
  57. 26
      app/src/main/java/net/pokeranalytics/android/ui/modules/feed/NewDataMenuActivity.kt
  58. 22
      app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt
  59. 34
      app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersFragment.kt
  60. 3
      app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersListFragment.kt
  61. 261
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/editor/EditorAdapter.kt
  62. 42
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/editor/EditorFragment.kt
  63. 45
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerFragment.kt
  64. 20
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/KeyboardActionView.kt
  65. 22
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/KeyboardAmountView.kt
  66. 20
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/KeyboardCardView.kt
  67. 20
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/views/RowHandHistoryViewHolder.kt
  68. 43
      app/src/main/java/net/pokeranalytics/android/ui/modules/session/SessionFragment.kt
  69. 29
      app/src/main/java/net/pokeranalytics/android/ui/view/LegendView.kt
  70. 19
      app/src/main/java/net/pokeranalytics/android/ui/view/MultiLineLegendView.kt
  71. 48
      app/src/main/java/net/pokeranalytics/android/ui/view/PlayerImageView.kt
  72. 16
      app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt
  73. 99
      app/src/main/java/net/pokeranalytics/android/ui/view/SessionRowView.kt
  74. 12
      app/src/main/java/net/pokeranalytics/android/ui/view/TransactionRowView.kt
  75. 6
      app/src/main/java/net/pokeranalytics/android/ui/viewmodel/GraphViewModel.kt
  76. 3
      app/src/main/java/net/pokeranalytics/android/ui/viewmodel/ReportHolder.kt
  77. 5
      app/src/main/java/net/pokeranalytics/android/ui/viewmodel/ReportViewModel.kt
  78. 3
      app/src/main/res/layout/row_session_view.xml
  79. 4
      build.gradle
  80. 2
      gradle.properties
  81. 4
      gradle/wrapper/gradle-wrapper.properties
  82. 1
      settings.gradle
  83. 42
      shared/build.gradle.kts
  84. 2
      shared/src/androidMain/AndroidManifest.xml
  85. 5
      shared/src/androidMain/kotlin/net/pokeranalytics/shared/Platform.kt
  86. 12
      shared/src/androidTest/kotlin/net/pokeranalytics/shared/androidTest.kt
  87. 7
      shared/src/commonMain/kotlin/net/pokeranalytics/shared/Greeting.kt
  88. 5
      shared/src/commonMain/kotlin/net/pokeranalytics/shared/Platform.kt
  89. 8
      shared/src/iosMain/kotlin/net/pokeranalytics/shared/Platform.kt
  90. 12
      shared/src/iosTest/kotlin/net/pokeranalytics/shared/iosTest.kt

@ -1,6 +1,6 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' //apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
apply plugin: 'realm-android' apply plugin: 'realm-android'
// Crashlytics // Crashlytics
@ -93,6 +93,10 @@ android {
} }
} }
buildFeatures {
viewBinding true
}
} }
dependencies { dependencies {

@ -0,0 +1,84 @@
package net.pokeranalytics.android.calcul
import android.content.Context
import com.github.mikephil.charting.data.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.ComputedResults
import net.pokeranalytics.android.calculus.Point
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.graph.DataSetFactory
import kotlin.math.abs
// MPAndroidChart
fun ComputedResults.defaultStatEntries(stat: Stat, context: Context): DataSet<out Entry> {
return when (stat) {
Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES, Stat.HOURLY_DURATION -> this.barEntries(stat, context = context)
Stat.STANDARD_DEVIATION -> this.distributionEntries(stat, context)
else -> this.singleLineEntries(stat, context)
}
}
fun ComputedResults.singleLineEntries(stat: Stat, context: Context): LineDataSet {
val entries = mutableListOf<Entry>()
this.evolutionValues[stat]?.let { points ->
points.forEachIndexed { index, p ->
entries.add(Entry(index.toFloat(), p.y.toFloat(), p.data))
}
}
return DataSetFactory.lineDataSetInstance(entries, this.group.query.getName(context), context)
}
fun ComputedResults.durationEntries(stat: Stat, context: Context): LineDataSet {
val entries = mutableListOf<Entry>()
this.evolutionValues[stat]?.let { points ->
points.forEach { p ->
entries.add(Entry(p.x.toFloat(), p.y.toFloat(), p.data))
}
}
return DataSetFactory.lineDataSetInstance(entries, stat.name, context)
}
private fun ComputedResults.barEntries(stat: Stat, context: Context): BarDataSet {
val entries = mutableListOf<BarEntry>()
this.evolutionValues[stat]?.let { points ->
points.forEach { p ->
entries.add(BarEntry(p.x.toFloat(), p.y.toFloat(), p.data))
}
}
return DataSetFactory.barDataSetInstance(entries, stat.name, context)
}
private fun ComputedResults.distributionEntries(stat: Stat, context: Context): BarDataSet {
val colors = mutableListOf<Int>()
val entries = mutableListOf<BarEntry>()
this.evolutionValues[stat]?.let { points ->
val negative = mutableListOf<Point>()
val positive = mutableListOf<Point>()
points.sortByDescending { it.y }
points.forEach {
if (it.y < 0) {
negative.add(it)
} else {
positive.add(it)
}
}
negative.forEachIndexed { index, p ->
entries.add(BarEntry(index.toFloat(), abs(p.y.toFloat()), p.data))
colors.add(context.getColor(R.color.red))
}
positive.forEachIndexed { index, p ->
val x = negative.size + index.toFloat()
entries.add(BarEntry(x, p.y.toFloat(), p.data))
colors.add(context.getColor(R.color.green))
}
}
return DataSetFactory.barDataSetInstance(entries, stat.name, context, colors)
}

@ -0,0 +1,64 @@
package net.pokeranalytics.android.calcul
import android.content.Context
import com.github.mikephil.charting.data.BarDataSet
import com.github.mikephil.charting.data.BarEntry
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineDataSet
import net.pokeranalytics.android.calculus.Report
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.graph.DataSetFactory
import net.pokeranalytics.android.util.ColorUtils
/**
* Returns the list of entries corresponding to the provided [stat]
* One value will be returned by result
*/
fun Report.lineEntries(stat: Stat? = null, context: Context): LineDataSet {
val entries = mutableListOf<Entry>()
val statToUse = stat ?: this.options.stats.firstOrNull()
val statName = statToUse?.name ?: ""
statToUse?.let {
this.results.forEachIndexed { index, results ->
results.computedStat(it)?.progressValue?.let { progressValue ->
entries.add(Entry(index.toFloat(), progressValue.toFloat(), results))
}
}
}
return DataSetFactory.lineDataSetInstance(entries, statName, context)
}
fun Report.barEntries(stat: Stat? = null, context: Context): BarDataSet {
val entries = mutableListOf<BarEntry>()
val statToUse = stat ?: options.stats.firstOrNull()
statToUse?.let {
this.results.forEachIndexed { index, results ->
val cs = results.computedStat(it)
cs?.let { computedStat ->
val barEntry = BarEntry(index.toFloat(), computedStat.value.toFloat(), results)
entries.add(barEntry)
}
}
}
val label = statToUse?.name ?: ""
return DataSetFactory.barDataSetInstance(entries, label, context)
}
fun Report.multiLineEntries(context: Context): List<LineDataSet> {
val dataSets = mutableListOf<LineDataSet>()
options.stats.forEach { stat ->
this.results.forEachIndexed { index, result ->
val ds = result.singleLineEntries(stat, context)
ds.color = ColorUtils.almostRandomColor(index, context)
dataSets.add(ds)
}
}
return dataSets
}

@ -2,7 +2,12 @@ package net.pokeranalytics.android.calculus
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.Criteria import net.pokeranalytics.android.model.Criteria
import net.pokeranalytics.android.ui.graph.AxisFormatting
enum class AxisFormatting {
DEFAULT,
X_DURATION,
Y_DURATION,
}
enum class AggregationType { enum class AggregationType {
SESSION, SESSION,

@ -0,0 +1,90 @@
package net.pokeranalytics.android.calculus
import io.realm.Realm
import io.realm.RealmResults
import net.pokeranalytics.android.model.filter.Query
import net.pokeranalytics.android.model.filter.QueryCondition
import net.pokeranalytics.android.model.realm.ComputableResult
import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.model.realm.SessionSet
/**
* A sessionGroup of computable items identified by a name
*/
class ComputableGroup(var query: Query, var stats: List<Stat>? = null) {
/**
* A subgroup used to compute stat variation
*/
var comparedGroup: ComputableGroup? = null
/**
* The computed statIds of the comparable sessionGroup
*/
var comparedComputedResults: ComputedResults? = null
/**
* A list of _conditions to get
*/
val conditions: List<QueryCondition>
get() {
return this.query.conditions
}
/**
* The list of endedSessions to compute
*/
private var _computables: RealmResults<ComputableResult>? = null
/**
* Retrieves the computables on the relative [realm] filtered with the provided [conditions]
*/
fun computables(realm: Realm, sorted: Boolean = false): RealmResults<ComputableResult> {
// if computables exists and is valid (previous realm not closed)
this._computables?.let {
if (it.isValid) {
return it
}
}
val sortedField = if (sorted) "session.startDate" else null
val computables = Filter.queryOn<ComputableResult>(realm, this.query, sortedField)
this._computables = computables
return computables
}
/**
* The list of sets to compute
*/
private var _sessionSets: RealmResults<SessionSet>? = null
/**
* Retrieves the session sets on the relative [realm] filtered with the provided [conditions]
*/
fun sessionSets(realm: Realm, sorted: Boolean = false): RealmResults<SessionSet> {
// if computables exists and is valid (previous realm not closed)
this._sessionSets?.let {
if (it.isValid) {
return it
}
}
val sortedField = if (sorted) SessionSet.Field.START_DATE.identifier else null
val sets = Filter.queryOn<SessionSet>(realm, this.query, sortedField)
this._sessionSets = sets
return sets
}
fun cleanup() {
this._computables = null
this._sessionSets = null
}
val isEmpty: Boolean
get() {
return this._computables?.isEmpty() ?: true
}
}

@ -1,25 +1,14 @@
package net.pokeranalytics.android.calculus package net.pokeranalytics.android.calculus
import android.content.Context import android.content.Context
import com.github.mikephil.charting.data.*
import io.realm.Realm
import io.realm.RealmResults
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.filter.Query
import net.pokeranalytics.android.model.filter.QueryCondition
import net.pokeranalytics.android.model.interfaces.GraphIdentifiableEntry import net.pokeranalytics.android.model.interfaces.GraphIdentifiableEntry
import net.pokeranalytics.android.model.realm.ComputableResult
import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.model.realm.SessionSet
import net.pokeranalytics.android.ui.fragment.GraphFragment import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.graph.DataSetFactory import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.ui.graph.GraphUnderlyingEntry import net.pokeranalytics.android.ui.graph.GraphUnderlyingEntry
import net.pokeranalytics.android.ui.view.DefaultLegendValues import net.pokeranalytics.android.ui.view.DefaultLegendValues
import net.pokeranalytics.android.ui.view.LegendContent import net.pokeranalytics.android.ui.view.LegendContent
import net.pokeranalytics.android.util.ColorUtils
import net.pokeranalytics.android.util.TextFormat import net.pokeranalytics.android.util.TextFormat
import kotlin.math.abs
/** /**
* The class returned after performing calculation in the Calculator object * The class returned after performing calculation in the Calculator object
@ -43,138 +32,11 @@ class Report(var options: Calculator.Options) {
this._results.add(result) this._results.add(result)
} }
/**
* Returns the list of entries corresponding to the provided [stat]
* One value will be returned by result
*/
fun lineEntries(stat: Stat? = null, context: Context): LineDataSet {
val entries = mutableListOf<Entry>()
val statToUse = stat ?: options.stats.firstOrNull()
val statName = statToUse?.name ?: ""
statToUse?.let {
this._results.forEachIndexed { index, results ->
results.computedStat(it)?.progressValue?.let { progressValue ->
entries.add(Entry(index.toFloat(), progressValue.toFloat(), results))
}
}
}
return DataSetFactory.lineDataSetInstance(entries, statName, context)
}
fun barEntries(stat: Stat? = null, context: Context): BarDataSet {
val entries = mutableListOf<BarEntry>()
val statToUse = stat ?: options.stats.firstOrNull()
statToUse?.let {
this._results.forEachIndexed { index, results ->
val cs = results.computedStat(it)
cs?.let { computedStat ->
val barEntry = BarEntry(index.toFloat(), computedStat.value.toFloat(), results)
entries.add(barEntry)
}
}
}
val label = statToUse?.name ?: ""
return DataSetFactory.barDataSetInstance(entries, label, context)
}
fun multiLineEntries(context: Context): List<LineDataSet> {
val dataSets = mutableListOf<LineDataSet>()
options.stats.forEach { stat ->
this._results.forEachIndexed { index, result ->
val ds = result.singleLineEntries(stat, context)
ds.color = ColorUtils.almostRandomColor(index, context)
dataSets.add(ds)
}
}
return dataSets
}
} }
/**
* A sessionGroup of computable items identified by a name
*/
class ComputableGroup(var query: Query, var stats: List<Stat>? = null) {
/**
* A subgroup used to compute stat variation
*/
var comparedGroup: ComputableGroup? = null
/**
* The computed statIds of the comparable sessionGroup
*/
var comparedComputedResults: ComputedResults? = null
/**
* A list of _conditions to get
*/
val conditions: List<QueryCondition>
get() {
return this.query.conditions
}
/**
* The list of endedSessions to compute
*/
private var _computables: RealmResults<ComputableResult>? = null
/**
* Retrieves the computables on the relative [realm] filtered with the provided [conditions]
*/
fun computables(realm: Realm, sorted: Boolean = false): RealmResults<ComputableResult> {
// if computables exists and is valid (previous realm not closed)
this._computables?.let {
if (it.isValid) {
return it
}
}
val sortedField = if (sorted) "session.startDate" else null
val computables = Filter.queryOn<ComputableResult>(realm, this.query, sortedField)
this._computables = computables
return computables
}
/**
* The list of sets to compute
*/
private var _sessionSets: RealmResults<SessionSet>? = null
/**
* Retrieves the session sets on the relative [realm] filtered with the provided [conditions]
*/
fun sessionSets(realm: Realm, sorted: Boolean = false): RealmResults<SessionSet> {
// if computables exists and is valid (previous realm not closed)
this._sessionSets?.let {
if (it.isValid) {
return it
}
}
val sortedField = if (sorted) SessionSet.Field.START_DATE.identifier else null
val sets = Filter.queryOn<SessionSet>(realm, this.query, sortedField)
this._sessionSets = sets
return sets
}
fun cleanup() {
this._computables = null
this._sessionSets = null
}
val isEmpty: Boolean
get() {
return this._computables?.isEmpty() ?: true
}
class Point(val x: Double, val y: Double, val data: Any) {
constructor(y: Double, data: Any) : this(0.0, y, data)
} }
class ComputedResults(group: ComputableGroup, class ComputedResults(group: ComputableGroup,
@ -196,6 +58,10 @@ class ComputedResults(group: ComputableGroup,
private val allStats: Collection<ComputedStat> private val allStats: Collection<ComputedStat>
get() { return this._computedStats.values } get() { return this._computedStats.values }
val evolutionValues: Map<Stat, MutableList<Point>>
get() {
return this._evolutionValues
}
/** /**
* Adds a value to the evolution values * Adds a value to the evolution values
@ -355,79 +221,6 @@ class ComputedResults(group: ComputableGroup,
this.consolidateProgressStats() this.consolidateProgressStats()
} }
// MPAndroidChart
fun defaultStatEntries(stat: Stat, context: Context): DataSet<out Entry> {
return when (stat) {
Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES, Stat.HOURLY_DURATION -> this.barEntries(stat, context = context)
Stat.STANDARD_DEVIATION -> this.distributionEntries(stat, context)
else -> this.singleLineEntries(stat, context)
}
}
fun singleLineEntries(stat: Stat, context: Context): LineDataSet {
val entries = mutableListOf<Entry>()
this._evolutionValues[stat]?.let { points ->
points.forEachIndexed { index, p ->
entries.add(Entry(index.toFloat(), p.y.toFloat(), p.data))
}
}
return DataSetFactory.lineDataSetInstance(entries, this.group.query.getName(context), context)
}
fun durationEntries(stat: Stat, context: Context): LineDataSet {
val entries = mutableListOf<Entry>()
this._evolutionValues[stat]?.let { points ->
points.forEach { p ->
entries.add(Entry(p.x.toFloat(), p.y.toFloat(), p.data))
}
}
return DataSetFactory.lineDataSetInstance(entries, stat.name, context)
}
private fun barEntries(stat: Stat, context: Context): BarDataSet {
val entries = mutableListOf<BarEntry>()
this._evolutionValues[stat]?.let { points ->
points.forEach { p ->
entries.add(BarEntry(p.x.toFloat(), p.y.toFloat(), p.data))
}
}
return DataSetFactory.barDataSetInstance(entries, stat.name, context)
}
private fun distributionEntries(stat: Stat, context: Context): BarDataSet {
val colors = mutableListOf<Int>()
val entries = mutableListOf<BarEntry>()
this._evolutionValues[stat]?.let { points ->
val negative = mutableListOf<Point>()
val positive = mutableListOf<Point>()
points.sortByDescending { it.y }
points.forEach {
if (it.y < 0) {
negative.add(it)
} else {
positive.add(it)
}
}
negative.forEachIndexed { index, p ->
entries.add(BarEntry(index.toFloat(), abs(p.y.toFloat()), p.data))
colors.add(context.getColor(R.color.red))
}
positive.forEachIndexed { index, p ->
val x = negative.size + index.toFloat()
entries.add(BarEntry(x, p.y.toFloat(), p.data))
colors.add(context.getColor(R.color.green))
}
}
return DataSetFactory.barDataSetInstance(entries, stat.name, context, colors)
}
val isEmpty: Boolean val isEmpty: Boolean
get() { get() {
return this.group.isEmpty return this.group.isEmpty
@ -449,18 +242,18 @@ class ComputedResults(group: ComputableGroup,
override fun legendValues( override fun legendValues(
stat: Stat, stat: Stat,
entry: Entry, total: Double,
style: GraphFragment.Style, style: Graph.Style,
groupName: String, groupName: String,
context: Context context: Context
): LegendContent { ): LegendContent {
when (style) { when (style) {
GraphFragment.Style.BAR -> { Graph.Style.BAR -> {
return when (stat) { return when (stat) {
Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES, Stat.WIN_RATIO -> { Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES, Stat.WIN_RATIO -> {
val totalStatValue = stat.textFormat(entry.y.toDouble(), currency = null) val totalStatValue = stat.textFormat(total, currency = null)
DefaultLegendValues(this.entryTitle(context), totalStatValue) DefaultLegendValues(this.entryTitle(context), totalStatValue)
} }
else -> { else -> {
@ -474,12 +267,12 @@ class ComputedResults(group: ComputableGroup,
return when (stat) { return when (stat) {
Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES, Stat.WIN_RATIO -> { Stat.NUMBER_OF_SETS, Stat.NUMBER_OF_GAMES, Stat.WIN_RATIO -> {
val totalStatValue = stat.textFormat(entry.y.toDouble(), currency = null) val totalStatValue = stat.textFormat(total, currency = null)
DefaultLegendValues(this.entryTitle(context), totalStatValue) DefaultLegendValues(this.entryTitle(context), totalStatValue)
} }
else -> { else -> {
val entryValue = this.formattedValue(stat) val entryValue = this.formattedValue(stat)
val totalStatValue = stat.textFormat(entry.y.toDouble(), currency = null) val totalStatValue = stat.textFormat(total, currency = null)
DefaultLegendValues(this.entryTitle(context), entryValue, totalStatValue) DefaultLegendValues(this.entryTitle(context), entryValue, totalStatValue)
} }
} }
@ -488,10 +281,4 @@ class ComputedResults(group: ComputableGroup,
} }
} }
}
class Point(val x: Double, val y: Double, val data: Any) {
constructor(y: Double, data: Any) : this(0.0, y, data)
} }

@ -1,7 +1,6 @@
package net.pokeranalytics.android.model.realm package net.pokeranalytics.android.model.realm
import android.content.Context import android.content.Context
import com.github.mikephil.charting.data.Entry
import io.realm.Realm import io.realm.Realm
import io.realm.RealmList import io.realm.RealmList
import io.realm.RealmObject import io.realm.RealmObject
@ -31,6 +30,7 @@ import net.pokeranalytics.android.model.utils.CrashLogging
import net.pokeranalytics.android.model.utils.SessionSetManager import net.pokeranalytics.android.model.utils.SessionSetManager
import net.pokeranalytics.android.ui.adapter.UnmanagedRowRepresentableException import net.pokeranalytics.android.ui.adapter.UnmanagedRowRepresentableException
import net.pokeranalytics.android.ui.fragment.GraphFragment import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.ui.view.* import net.pokeranalytics.android.ui.view.*
import net.pokeranalytics.android.ui.view.rowrepresentable.SessionRow import net.pokeranalytics.android.ui.view.rowrepresentable.SessionRow
import net.pokeranalytics.android.util.NULL_TEXT import net.pokeranalytics.android.util.NULL_TEXT
@ -896,14 +896,14 @@ open class Session : RealmObject(), Savable, Editable, RowRepresentable, Timed,
override fun legendValues( override fun legendValues(
stat: Stat, stat: Stat,
entry: Entry, total: Double,
style: GraphFragment.Style, style: Graph.Style,
groupName: String, groupName: String,
context: Context context: Context
): LegendContent { ): LegendContent {
when (style) { when (style) {
GraphFragment.Style.MULTILINE -> { Graph.Style.MULTILINE -> {
val secondTitle = stat.localizedTitle(context) val secondTitle = stat.localizedTitle(context)
val entryValue = this.formattedValue(stat) val entryValue = this.formattedValue(stat)
@ -929,7 +929,7 @@ open class Session : RealmObject(), Savable, Editable, RowRepresentable, Timed,
DefaultLegendValues(this.entryTitle(context), left, right) DefaultLegendValues(this.entryTitle(context), left, right)
} }
else -> { else -> {
super<Timed>.legendValues(stat, entry, style, groupName, context) super<Timed>.legendValues(stat, total, style, groupName, context)
} }
} }
} }

@ -1,7 +1,6 @@
package net.pokeranalytics.android.model.realm package net.pokeranalytics.android.model.realm
import android.content.Context import android.content.Context
import com.github.mikephil.charting.data.Entry
import io.realm.Realm import io.realm.Realm
import io.realm.RealmObject import io.realm.RealmObject
import io.realm.annotations.Ignore import io.realm.annotations.Ignore
@ -12,7 +11,7 @@ import net.pokeranalytics.android.model.filter.Filterable
import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.filter.QueryCondition
import net.pokeranalytics.android.model.interfaces.* import net.pokeranalytics.android.model.interfaces.*
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.fragment.GraphFragment import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.ui.view.DefaultLegendValues import net.pokeranalytics.android.ui.view.DefaultLegendValues
import net.pokeranalytics.android.ui.view.LegendContent import net.pokeranalytics.android.ui.view.LegendContent
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
@ -163,14 +162,14 @@ open class Transaction : RealmObject(), Manageable, StaticRowRepresentableDataSo
override fun legendValues( override fun legendValues(
stat: Stat, stat: Stat,
entry: Entry, total: Double,
style: GraphFragment.Style, style: Graph.Style,
groupName: String, groupName: String,
context: Context context: Context
): LegendContent { ): LegendContent {
val entryValue = this.formattedValue(stat) val entryValue = this.formattedValue(stat)
val totalStatValue = stat.textFormat(entry.y.toDouble(), currency = null) val totalStatValue = stat.textFormat(total, currency = null)
val leftName = context.getString(R.string.amount) val leftName = context.getString(R.string.amount)
return DefaultLegendValues(this.entryTitle(context), entryValue, totalStatValue, leftName = leftName) return DefaultLegendValues(this.entryTitle(context), entryValue, totalStatValue, leftName = leftName)
} }

@ -8,8 +8,8 @@ import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.activity_color_picker.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.ActivityColorPickerBinding
import net.pokeranalytics.android.ui.activity.components.BaseActivity import net.pokeranalytics.android.ui.activity.components.BaseActivity
class ColorPickerActivity : BaseActivity() { class ColorPickerActivity : BaseActivity() {
@ -33,15 +33,17 @@ class ColorPickerActivity : BaseActivity() {
} }
override fun onCreate(savedInstanceState: Bundle?) { private lateinit var binding: ActivityColorPickerBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { // used to fix Oreo crash if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { // used to fix Oreo crash
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
} }
binding = ActivityColorPickerBinding.inflate(layoutInflater)
setContentView(R.layout.activity_color_picker) setContentView(binding.root)
this.title = getString(R.string.select_a_color)
initUI() initUI()
} }
@ -49,29 +51,29 @@ class ColorPickerActivity : BaseActivity() {
* Init UI * Init UI
*/ */
private fun initUI() { private fun initUI() {
color1.setOnClickListener { manageSelectedColor(it) } binding.color1.setOnClickListener { manageSelectedColor(it) }
color2.setOnClickListener { manageSelectedColor(it) } binding.color2.setOnClickListener { manageSelectedColor(it) }
color3.setOnClickListener { manageSelectedColor(it) } binding.color3.setOnClickListener { manageSelectedColor(it) }
color4.setOnClickListener { manageSelectedColor(it) } binding.color4.setOnClickListener { manageSelectedColor(it) }
color5.setOnClickListener { manageSelectedColor(it) } binding.color5.setOnClickListener { manageSelectedColor(it) }
color6.setOnClickListener { manageSelectedColor(it) } binding.color6.setOnClickListener { manageSelectedColor(it) }
color7.setOnClickListener { manageSelectedColor(it) } binding.color7.setOnClickListener { manageSelectedColor(it) }
color8.setOnClickListener { manageSelectedColor(it) } binding.color8.setOnClickListener { manageSelectedColor(it) }
color9.setOnClickListener { manageSelectedColor(it) } binding.color9.setOnClickListener { manageSelectedColor(it) }
} }
private fun manageSelectedColor(view: View) { private fun manageSelectedColor(view: View) {
val color = when(view) { val color = when(view) {
color1 -> getColor(R.color.player_color_1) binding.color1 -> getColor(R.color.player_color_1)
color2 -> getColor(R.color.player_color_2) binding.color2 -> getColor(R.color.player_color_2)
color3 -> getColor(R.color.player_color_3) binding.color3 -> getColor(R.color.player_color_3)
color4 -> getColor(R.color.player_color_4) binding.color4 -> getColor(R.color.player_color_4)
color5 -> getColor(R.color.player_color_5) binding.color5 -> getColor(R.color.player_color_5)
color6 -> getColor(R.color.player_color_6) binding.color6 -> getColor(R.color.player_color_6)
color7 -> getColor(R.color.player_color_7) binding.color7 -> getColor(R.color.player_color_7)
color8 -> getColor(R.color.player_color_8) binding.color8 -> getColor(R.color.player_color_8)
color9 -> getColor(R.color.player_color_9) binding.color9 -> getColor(R.color.player_color_9)
else -> getColor(R.color.player_color_1) else -> getColor(R.color.player_color_1)
} }

@ -3,12 +3,13 @@ package net.pokeranalytics.android.ui.activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import kotlinx.android.synthetic.main.activity_gdpr.* import net.pokeranalytics.android.databinding.ActivityGdprBinding
import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.activity.components.BaseActivity import net.pokeranalytics.android.ui.activity.components.BaseActivity
class GDPRActivity : BaseActivity() { class GDPRActivity : BaseActivity() {
private lateinit var binding: ActivityGdprBinding
companion object { companion object {
fun newInstance(context: Context) { fun newInstance(context: Context) {
val intent = Intent(context, GDPRActivity::class.java) val intent = Intent(context, GDPRActivity::class.java)
@ -18,7 +19,8 @@ class GDPRActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_gdpr) binding = ActivityGdprBinding.inflate(layoutInflater)
setContentView(binding.root)
initUI() initUI()
} }
@ -27,10 +29,8 @@ class GDPRActivity : BaseActivity() {
* Init UI * Init UI
*/ */
private fun initUI() { private fun initUI() {
setSupportActionBar(binding.toolbar)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
} }
} }

@ -6,11 +6,12 @@ import android.os.Bundle
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import com.github.mikephil.charting.data.BarDataSet import com.github.mikephil.charting.data.BarDataSet
import com.github.mikephil.charting.data.LineDataSet import com.github.mikephil.charting.data.LineDataSet
import kotlinx.android.synthetic.main.activity_graph.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.ActivityGraphBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.ui.activity.components.BaseActivity import net.pokeranalytics.android.ui.activity.components.BaseActivity
import net.pokeranalytics.android.ui.fragment.GraphFragment import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.ui.viewmodel.GraphViewModel import net.pokeranalytics.android.ui.viewmodel.GraphViewModel
import net.pokeranalytics.android.ui.viewmodel.ViewModelHolder import net.pokeranalytics.android.ui.viewmodel.ViewModelHolder
@ -25,7 +26,7 @@ class GraphActivity : BaseActivity(), ViewModelHolder {
private var lineDataSets: List<LineDataSet>? = null private var lineDataSets: List<LineDataSet>? = null
private var barDataSets: List<BarDataSet>? = null private var barDataSets: List<BarDataSet>? = null
private var style: GraphFragment.Style? = null private var style: Graph.Style? = null
private var activityTitle: String? = null private var activityTitle: String? = null
/*** /***
@ -33,7 +34,7 @@ class GraphActivity : BaseActivity(), ViewModelHolder {
*/ */
fun newLineInstance(context: Context, lineDataSets: List<LineDataSet>, title: String? = null) { fun newLineInstance(context: Context, lineDataSets: List<LineDataSet>, title: String? = null) {
this.lineDataSets = lineDataSets this.lineDataSets = lineDataSets
this.style = GraphFragment.Style.LINE this.style = Graph.Style.LINE
this.activityTitle = title this.activityTitle = title
val intent = Intent(context, GraphActivity::class.java) val intent = Intent(context, GraphActivity::class.java)
@ -45,7 +46,7 @@ class GraphActivity : BaseActivity(), ViewModelHolder {
*/ */
fun newBarInstance(context: Context, barDataSets: List<BarDataSet>, title: String? = null) { fun newBarInstance(context: Context, barDataSets: List<BarDataSet>, title: String? = null) {
this.barDataSets = barDataSets this.barDataSets = barDataSets
this.style = GraphFragment.Style.BAR this.style = Graph.Style.BAR
this.activityTitle = title this.activityTitle = title
val intent = Intent(context, GraphActivity::class.java) val intent = Intent(context, GraphActivity::class.java)
@ -54,12 +55,16 @@ class GraphActivity : BaseActivity(), ViewModelHolder {
} }
private lateinit var binding: ActivityGraphBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_graph) binding = ActivityGraphBinding.inflate(layoutInflater)
setContentView(binding.root)
initUI() initUI()
} }
/** /**
* Init UI * Init UI
*/ */
@ -68,7 +73,7 @@ class GraphActivity : BaseActivity(), ViewModelHolder {
this.model.title = activityTitle this.model.title = activityTitle
this.model.title?.let { this.model.title?.let {
setSupportActionBar(toolbar) setSupportActionBar(binding.toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
title = activityTitle title = activityTitle
activityTitle = null activityTitle = null

@ -7,9 +7,9 @@ import android.os.Build
import android.os.Bundle import android.os.Bundle
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import io.realm.RealmResults import io.realm.RealmResults
import kotlinx.android.synthetic.main.activity_home.*
import net.pokeranalytics.android.BuildConfig import net.pokeranalytics.android.BuildConfig
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.ActivityHomeBinding
import net.pokeranalytics.android.model.realm.Currency import net.pokeranalytics.android.model.realm.Currency
import net.pokeranalytics.android.ui.activity.components.BaseActivity import net.pokeranalytics.android.ui.activity.components.BaseActivity
import net.pokeranalytics.android.ui.adapter.HomePagerAdapter import net.pokeranalytics.android.ui.adapter.HomePagerAdapter
@ -56,6 +56,8 @@ class HomeActivity : BaseActivity() {
this.homePagerAdapter?.activityResumed() this.homePagerAdapter?.activityResumed()
} }
private lateinit var binding: ActivityHomeBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -68,7 +70,8 @@ class HomeActivity : BaseActivity() {
} }
} }
setContentView(R.layout.activity_home) binding = ActivityHomeBinding.inflate(layoutInflater)
setContentView(binding.root)
observeRealmObjects() observeRealmObjects()
initUI() initUI()
@ -141,10 +144,12 @@ class HomeActivity : BaseActivity() {
*/ */
private fun initUI() { private fun initUI() {
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener) binding.navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
navigation.selectedItemId = R.id.navigation_history binding.navigation.selectedItemId = R.id.navigation_history
homePagerAdapter = HomePagerAdapter(supportFragmentManager) homePagerAdapter = HomePagerAdapter(supportFragmentManager)
val viewPager = binding.viewPager
viewPager.offscreenPageLimit = 5 viewPager.offscreenPageLimit = 5
viewPager.enablePaging = false viewPager.enablePaging = false
viewPager.adapter = homePagerAdapter viewPager.adapter = homePagerAdapter
@ -168,7 +173,7 @@ class HomeActivity : BaseActivity() {
* Display a new fragment * Display a new fragment
*/ */
private fun displayFragment(index: Int) { private fun displayFragment(index: Int) {
viewPager.setCurrentItem(index, false) binding.viewPager.setCurrentItem(index, false)
} }
} }

@ -10,6 +10,7 @@ import net.pokeranalytics.android.ui.modules.calendar.CalendarFragment
import net.pokeranalytics.android.ui.modules.feed.FeedFragment import net.pokeranalytics.android.ui.modules.feed.FeedFragment
import net.pokeranalytics.android.ui.fragment.GraphFragment import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.fragment.components.BaseFragment import net.pokeranalytics.android.ui.fragment.components.BaseFragment
import net.pokeranalytics.android.ui.graph.Graph
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
/** /**
@ -21,8 +22,8 @@ class ComparisonChartPagerAdapter(val context: Context, fragmentManager: Fragmen
override fun getItem(position: Int): BaseFragment { override fun getItem(position: Int): BaseFragment {
return when (position) { return when (position) {
0 -> GraphFragment.newInstance(GraphFragment.Style.BAR) 0 -> GraphFragment.newInstance(Graph.Style.BAR)
1 -> GraphFragment.newInstance(GraphFragment.Style.MULTILINE) 1 -> GraphFragment.newInstance(Graph.Style.MULTILINE)
2 -> CalendarFragment.newInstance() 2 -> CalendarFragment.newInstance()
else -> FeedFragment.newInstance() else -> FeedFragment.newInstance()
} }

@ -8,6 +8,7 @@ import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.ui.fragment.GraphFragment import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.fragment.components.BaseFragment import net.pokeranalytics.android.ui.fragment.components.BaseFragment
import net.pokeranalytics.android.ui.fragment.report.ComposableTableReportFragment import net.pokeranalytics.android.ui.fragment.report.ComposableTableReportFragment
import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.ui.viewmodel.ReportHolder import net.pokeranalytics.android.ui.viewmodel.ReportHolder
/** /**
@ -19,8 +20,8 @@ class ReportPagerAdapter(private val context: Context,
override fun getItem(position: Int): BaseFragment { override fun getItem(position: Int): BaseFragment {
return when (position) { return when (position) {
0 -> GraphFragment.newInstance(style = GraphFragment.Style.BAR) 0 -> GraphFragment.newInstance(Graph.Style.BAR)
1 -> GraphFragment.newInstance(style = GraphFragment.Style.MULTILINE) 1 -> GraphFragment.newInstance(Graph.Style.MULTILINE)
2 -> { 2 -> {
val report = this.reportHolder.report val report = this.reportHolder.report
ComposableTableReportFragment.newInstance(report) ComposableTableReportFragment.newInstance(report)
@ -33,7 +34,7 @@ class ReportPagerAdapter(private val context: Context,
return 3 return 3
} }
override fun getPageTitle(position: Int): CharSequence? { override fun getPageTitle(position: Int): CharSequence {
return when(position) { return when(position) {
0 -> context.getString(R.string.bars) 0 -> context.getString(R.string.bars)
1 -> context.getString(R.string.lines) 1 -> context.getString(R.string.lines)

@ -14,9 +14,9 @@ import android.view.View
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.widget.ImageView import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.AppCompatTextView
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
@ -147,7 +147,7 @@ fun showAlertDialog(
builder.show() builder.show()
} }
fun AppCompatTextView.setTextFormat(textFormat: TextFormat, context: Context) { fun TextView.setTextFormat(textFormat: TextFormat, context: Context) {
this.setTextColor(textFormat.getColor(context)) this.setTextColor(textFormat.getColor(context))
this.text = textFormat.text this.text = textFormat.text
} }

@ -2,8 +2,8 @@ package net.pokeranalytics.android.ui.fragment
import android.os.Bundle import android.os.Bundle
import android.view.* import android.view.*
import kotlinx.android.synthetic.main.fragment_comparison_chart.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentComparisonChartBinding
import net.pokeranalytics.android.ui.modules.bankroll.BankrollActivity import net.pokeranalytics.android.ui.modules.bankroll.BankrollActivity
import net.pokeranalytics.android.ui.activity.SettingsActivity import net.pokeranalytics.android.ui.activity.SettingsActivity
import net.pokeranalytics.android.ui.adapter.ComparisonChartPagerAdapter import net.pokeranalytics.android.ui.adapter.ComparisonChartPagerAdapter
@ -38,12 +38,19 @@ class ComparisonChartFragment : BaseFragment(), StaticRowRepresentableDataSource
private lateinit var viewPagerAdapter: ComparisonChartPagerAdapter private lateinit var viewPagerAdapter: ComparisonChartPagerAdapter
private var comparisonChartMenu: Menu? = null private var comparisonChartMenu: Menu? = null
private var _binding: FragmentComparisonChartBinding? = null
private val binding get() = _binding!!
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
// Life Cycle // Life Cycle
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_comparison_chart, container, false) _binding = FragmentComparisonChartBinding.inflate(inflater, container, false)
return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -97,9 +104,9 @@ class ComparisonChartFragment : BaseFragment(), StaticRowRepresentableDataSource
parentActivity?.let { parentActivity?.let {
viewPagerAdapter = ComparisonChartPagerAdapter(requireContext(), it.supportFragmentManager) viewPagerAdapter = ComparisonChartPagerAdapter(requireContext(), it.supportFragmentManager)
viewPager.adapter = viewPagerAdapter binding.viewPager.adapter = viewPagerAdapter
viewPager.offscreenPageLimit = 2 binding.viewPager.offscreenPageLimit = 2
tabs.setupWithViewPager(viewPager) binding.tabs.setupWithViewPager(binding.viewPager)
} }
} }

@ -8,8 +8,8 @@ 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 kotlinx.android.synthetic.main.fragment_data_list.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentCurrenciesBinding
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
@ -71,10 +71,20 @@ class CurrenciesFragment : BaseFragment(), StaticRowRepresentableDataSource, Row
override val viewType: Int = RowViewType.TITLE_VALUE.ordinal override val viewType: Int = RowViewType.TITLE_VALUE.ordinal
} }
private var _binding: FragmentCurrenciesBinding? = null
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { // Life Cycle
return inflater.inflate(R.layout.fragment_currencies, container, false)
} override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = FragmentCurrenciesBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -120,7 +130,7 @@ class CurrenciesFragment : BaseFragment(), StaticRowRepresentableDataSource, Row
val viewManager = LinearLayoutManager(requireContext()) val viewManager = LinearLayoutManager(requireContext())
val dataListAdapter = RowRepresentableAdapter(this, this) val dataListAdapter = RowRepresentableAdapter(this, this)
recyclerView.apply { binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
adapter = dataListAdapter adapter = dataListAdapter

@ -13,12 +13,12 @@ import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.highlight.Highlight import com.github.mikephil.charting.highlight.Highlight
import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet
import com.github.mikephil.charting.listener.OnChartValueSelectedListener import com.github.mikephil.charting.listener.OnChartValueSelectedListener
import kotlinx.android.synthetic.main.fragment_graph.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.databinding.FragmentGraphBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.interfaces.ObjectIdentifier import net.pokeranalytics.android.model.interfaces.ObjectIdentifier
import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.ui.fragment.components.RealmFragment
import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.ui.graph.GraphUnderlyingEntry import net.pokeranalytics.android.ui.graph.GraphUnderlyingEntry
import net.pokeranalytics.android.ui.graph.setStyle import net.pokeranalytics.android.ui.graph.setStyle
import net.pokeranalytics.android.ui.view.LegendView import net.pokeranalytics.android.ui.view.LegendView
@ -38,18 +38,12 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
return this.graphDataProvider.stat return this.graphDataProvider.stat
} }
enum class Style {
LINE,
BAR,
MULTILINE,
}
companion object { companion object {
/** /**
* Create new instance * Create new instance
*/ */
fun newInstance(style: Style): GraphFragment { fun newInstance(style: Graph.Style): GraphFragment {
val fragment = GraphFragment() val fragment = GraphFragment()
val bundle = Bundle() val bundle = Bundle()
bundle.putSerializable(BundleKey.STYLE.value, style.ordinal) bundle.putSerializable(BundleKey.STYLE.value, style.ordinal)
@ -59,16 +53,27 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
} }
private var style: Style = Style.LINE private var style: Graph.Style = Graph.Style.LINE
private lateinit var legendView: LegendView private lateinit var legendView: LegendView
private var chartView: BarLineChartBase<*>? = null private var chartView: BarLineChartBase<*>? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { private var _binding: FragmentGraphBinding? = null
super.onCreateView(inflater, container, savedInstanceState) private val binding get() = _binding!!
return inflater.inflate(R.layout.fragment_graph, container, false)
} // Life Cycle
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentGraphBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -79,7 +84,7 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
private fun initData() { private fun initData() {
val styleOrdinal = this.arguments?.getInt(BundleKey.STYLE.value) ?: throw PAIllegalStateException("Missing style key in bundle") val styleOrdinal = this.arguments?.getInt(BundleKey.STYLE.value) ?: throw PAIllegalStateException("Missing style key in bundle")
this.style = Style.values()[styleOrdinal] this.style = Graph.Style.values()[styleOrdinal]
this.graphDataProvider = (requireActivity() as ViewModelHolder).model as GraphDataProvider this.graphDataProvider = (requireActivity() as ViewModelHolder).model as GraphDataProvider
} }
@ -90,14 +95,14 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
private fun initUI() { private fun initUI() {
this.legendView = when (this.style) { this.legendView = when (this.style) {
Style.MULTILINE -> MultiLineLegendView(requireContext()) Graph.Style.MULTILINE -> MultiLineLegendView(requireContext())
else -> LegendView(requireContext()) else -> LegendView(requireContext())
} }
this.legendContainer.addView(this.legendView) this.binding.legendContainer.addView(this.legendView)
} }
fun reload(style: Style) { fun reload(style: Graph.Style) {
this.style = style this.style = style
if (isAdded && !isDetached) { if (isAdded && !isDetached) {
loadGraph() loadGraph()
@ -109,14 +114,14 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
*/ */
private fun loadGraph() { private fun loadGraph() {
this.chartContainer.removeAllViews() this.binding.chartContainer.removeAllViews()
this.chartView = when (this.style) { this.chartView = when (this.style) {
Style.LINE, Style.MULTILINE -> { Graph.Style.LINE, Graph.Style.MULTILINE -> {
val dataSets = when (this.style) { val dataSets = when (this.style) {
Style.LINE -> listOf(this.graphDataProvider.lineDataSet(requireContext())) Graph.Style.LINE -> listOf(this.graphDataProvider.lineDataSet(requireContext()))
Style.MULTILINE -> this.graphDataProvider.multiLineDataSet(requireContext()) Graph.Style.MULTILINE -> this.graphDataProvider.multiLineDataSet(requireContext())
else -> throw PAIllegalStateException("Cannot happen") else -> throw PAIllegalStateException("Cannot happen")
} }
@ -136,7 +141,7 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
lineChart lineChart
} }
Style.BAR -> { Graph.Style.BAR -> {
val dataSets = listOf(this.graphDataProvider.barDataSet(requireContext())) val dataSets = listOf(this.graphDataProvider.barDataSet(requireContext()))
@ -165,7 +170,7 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
} }
} }
this.chartContainer.addView(this.chartView) this.binding.chartContainer.addView(this.chartView)
this.chartView?.setStyle(false, this.graphDataProvider.axisFormatting, requireContext()) this.chartView?.setStyle(false, this.graphDataProvider.axisFormatting, requireContext())
@ -199,7 +204,7 @@ class GraphFragment : RealmFragment(), OnChartValueSelectedListener {
val groupName = dataSet?.label ?: "" val groupName = dataSet?.label ?: ""
val color = dataSet?.color val color = dataSet?.color
val legendValue = statEntry.legendValues(stat, entry, this.style, groupName, requireContext()) val legendValue = statEntry.legendValues(stat, entry.y.toDouble(), this.style, groupName, requireContext())
this.legendView.setItemData(legendValue, color) this.legendView.setItemData(legendValue, color)
} else { } else {

@ -6,12 +6,11 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.fragment_import.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentImportBinding
import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.ui.fragment.components.RealmFragment
import net.pokeranalytics.android.util.csv.CSVImporter import net.pokeranalytics.android.util.csv.CSVImporter
import net.pokeranalytics.android.util.csv.ImportDelegate import net.pokeranalytics.android.util.csv.ImportDelegate
@ -19,7 +18,6 @@ import timber.log.Timber
import java.io.InputStream import java.io.InputStream
import java.text.NumberFormat import java.text.NumberFormat
import java.util.* import java.util.*
import kotlin.coroutines.CoroutineContext
class ImportFragment : RealmFragment(), ImportDelegate { class ImportFragment : RealmFragment(), ImportDelegate {
@ -30,7 +28,24 @@ class ImportFragment : RealmFragment(), ImportDelegate {
private lateinit var inputStream: InputStream private lateinit var inputStream: InputStream
private lateinit var importer: CSVImporter private lateinit var importer: CSVImporter
fun setData(path: String) { private var _binding: FragmentImportBinding? = null
private val binding get() = _binding!!
// Life Cycle
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentImportBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
fun setData(path: String) {
this.filePath = path this.filePath = path
} }
@ -38,11 +53,6 @@ class ImportFragment : RealmFragment(), ImportDelegate {
this.inputStream = inputStream this.inputStream = inputStream
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_import, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -53,15 +63,20 @@ class ImportFragment : RealmFragment(), ImportDelegate {
private fun initUI() { private fun initUI() {
this.imported.text = requireContext().getString(R.string.imported) val imported = binding.imported
this.total.text = requireContext().getString(R.string.total) val total = binding.total
val save = binding.save
val cancel = binding.cancel
imported.text = requireContext().getString(R.string.imported)
total.text = requireContext().getString(R.string.total)
this.save.isEnabled = false save.isEnabled = false
this.save.setOnClickListener { save.setOnClickListener {
this.end() this.end()
} }
this.cancel.setOnClickListener { cancel.setOnClickListener {
this.cancel() this.cancel()
this.end() this.end()
} }
@ -128,7 +143,7 @@ class ImportFragment : RealmFragment(), ImportDelegate {
private fun importDidFinish() { private fun importDidFinish() {
this.save.isEnabled = true binding.save.isEnabled = true
} }
@ -141,8 +156,8 @@ class ImportFragment : RealmFragment(), ImportDelegate {
// ImportDelegate // ImportDelegate
override fun parsingCountUpdate(importedCount: Int, totalCount: Int) { override fun parsingCountUpdate(importedCount: Int, totalCount: Int) {
this.counter.text = this.numberFormatter.format(importedCount) binding.counter.text = this.numberFormatter.format(importedCount)
this.totalCounter.text = this.numberFormatter.format(totalCount) binding.totalCounter.text = this.numberFormatter.format(totalCount)
} }
} }

@ -6,10 +6,10 @@ import android.os.Bundle
import android.view.* import android.view.*
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import io.realm.Realm import io.realm.Realm
import kotlinx.android.synthetic.main.fragment_report_creation.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.Calculator
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.databinding.FragmentReportCreationBinding
import net.pokeranalytics.android.model.Criteria import net.pokeranalytics.android.model.Criteria
import net.pokeranalytics.android.model.CustomFieldCriteria import net.pokeranalytics.android.model.CustomFieldCriteria
import net.pokeranalytics.android.model.realm.CustomField import net.pokeranalytics.android.model.realm.CustomField
@ -37,10 +37,21 @@ class ReportCreationFragment : RealmFragment(), RowRepresentableDataSource, RowR
private var currentRows: List<RowRepresentable> = listOf() private var currentRows: List<RowRepresentable> = listOf()
private var reportCreationMenu: Menu? = null private var reportCreationMenu: Menu? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { private var _binding: FragmentReportCreationBinding? = null
super.onCreateView(inflater, container, savedInstanceState) private val binding get() = _binding!!
return inflater.inflate(R.layout.fragment_report_creation, container, false)
} // Life Cycle
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentReportCreationBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -94,13 +105,13 @@ class ReportCreationFragment : RealmFragment(), RowRepresentableDataSource, RowR
//this.optionsAdapter.setHasStableIds(true) //this.optionsAdapter.setHasStableIds(true)
val viewManager = LinearLayoutManager(requireContext()) val viewManager = LinearLayoutManager(requireContext())
recyclerView.apply { binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
adapter = optionsAdapter adapter = optionsAdapter
} }
this.next.setOnClickListener { binding.next.setOnClickListener {
if (assistant.nextEnabled) { if (assistant.nextEnabled) {
this.assistant.nextStep() this.assistant.nextStep()
@ -126,9 +137,9 @@ class ReportCreationFragment : RealmFragment(), RowRepresentableDataSource, RowR
*/ */
private fun updateUIWithCurrentStep() { private fun updateUIWithCurrentStep() {
this.next.visibility = if (this.assistant.nextButtonShouldAppear) View.VISIBLE else View.GONE binding.next.visibility = if (this.assistant.nextButtonShouldAppear) View.VISIBLE else View.GONE
this.next.text = requireContext().getString(this.assistant.nextButtonTitleResId) binding.next.text = requireContext().getString(this.assistant.nextButtonTitleResId)
this.next.isEnabled = this.assistant.nextEnabled binding.next.isEnabled = this.assistant.nextEnabled
this.reportCreationMenu?.findItem(R.id.add)?.isVisible = this.assistant.addButtonShouldAppear this.reportCreationMenu?.findItem(R.id.add)?.isVisible = this.assistant.addButtonShouldAppear
val rows = mutableListOf<RowRepresentable>() val rows = mutableListOf<RowRepresentable>()
@ -198,7 +209,7 @@ class ReportCreationFragment : RealmFragment(), RowRepresentableDataSource, RowR
if (newStep) { if (newStep) {
this.updateUIWithCurrentStep() this.updateUIWithCurrentStep()
} else { } else {
this.next.isEnabled = this.assistant.nextEnabled binding.next.isEnabled = this.assistant.nextEnabled
this.optionsAdapter.notifyDataSetChanged() this.optionsAdapter.notifyDataSetChanged()
} }

@ -10,7 +10,6 @@ import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
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.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -18,6 +17,7 @@ import kotlinx.coroutines.launch
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.Calculator
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.databinding.FragmentReportsBinding
import net.pokeranalytics.android.model.Criteria import net.pokeranalytics.android.model.Criteria
import net.pokeranalytics.android.model.combined import net.pokeranalytics.android.model.combined
import net.pokeranalytics.android.model.interfaces.Deletable import net.pokeranalytics.android.model.interfaces.Deletable
@ -59,13 +59,21 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc
} }
} }
private var _binding: FragmentReportsBinding? = null
private val binding get() = _binding!!
// Life Cycle // Life Cycle
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_reports, container, false) _binding = FragmentReportsBinding.inflate(inflater, container, false)
} return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -119,13 +127,13 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc
val viewManager = LinearLayoutManager(requireContext()) val viewManager = LinearLayoutManager(requireContext())
recyclerView.apply { binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
adapter = dataListAdapter adapter = dataListAdapter
} }
this.addButton.setOnClickListener { binding.addButton.setOnClickListener {
ReportCreationActivity.newInstanceForResult(this, requireContext()) ReportCreationActivity.newInstanceForResult(this, requireContext())
} }

@ -15,9 +15,9 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.android.billingclient.api.Purchase import com.android.billingclient.api.Purchase
import com.google.android.play.core.review.ReviewManagerFactory import com.google.android.play.core.review.ReviewManagerFactory
import io.realm.Realm import io.realm.Realm
import kotlinx.android.synthetic.main.fragment_settings.*
import net.pokeranalytics.android.BuildConfig import net.pokeranalytics.android.BuildConfig
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentSettingsBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.realm.Currency import net.pokeranalytics.android.model.realm.Currency
@ -71,7 +71,24 @@ class SettingsFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRep
private lateinit var settingsAdapterRow: RowRepresentableAdapter private lateinit var settingsAdapterRow: RowRepresentableAdapter
override fun onCreate(savedInstanceState: Bundle?) { private var _binding: FragmentSettingsBinding? = null
private val binding get() = _binding!!
// Life Cycle
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentSettingsBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
AppGuard.registerListener(this) AppGuard.registerListener(this)
} }
@ -81,11 +98,6 @@ class SettingsFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRep
AppGuard.unregisterListener(this) AppGuard.unregisterListener(this)
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_settings, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initData() initData()
@ -227,7 +239,7 @@ class SettingsFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRep
val viewManager = LinearLayoutManager(requireContext()) val viewManager = LinearLayoutManager(requireContext())
settingsAdapterRow = RowRepresentableAdapter(this, this) settingsAdapterRow = RowRepresentableAdapter(this, this)
recyclerView.apply { binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
adapter = settingsAdapterRow adapter = settingsAdapterRow

@ -15,6 +15,8 @@ import net.pokeranalytics.android.calculus.Calculator
import net.pokeranalytics.android.calculus.ComputableGroup import net.pokeranalytics.android.calculus.ComputableGroup
import net.pokeranalytics.android.calculus.Report import net.pokeranalytics.android.calculus.Report
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.databinding.FragmentGraphBinding
import net.pokeranalytics.android.databinding.FragmentStatsBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.filter.Query import net.pokeranalytics.android.model.filter.Query
import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.filter.QueryCondition
@ -46,12 +48,21 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
} }
} }
// Life Cycle private var _binding: FragmentStatsBinding? = null
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { // Life Cycle
super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_stats, container, false) override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
} super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentStatsBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)

@ -22,8 +22,8 @@ import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.viewpager.widget.ViewPager import androidx.viewpager.widget.ViewPager
import com.android.billingclient.api.* import com.android.billingclient.api.*
import kotlinx.android.synthetic.main.fragment_subscription.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentSubscriptionBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.utils.CrashLogging import net.pokeranalytics.android.model.utils.CrashLogging
import net.pokeranalytics.android.ui.extensions.px import net.pokeranalytics.android.ui.extensions.px
@ -55,7 +55,23 @@ class SubscriptionFragment : BaseFragment(), SkuDetailsResponseListener, Purchas
private var selectedProduct: SkuDetails? = null private var selectedProduct: SkuDetails? = null
private var showSessionMessage = false private var showSessionMessage = false
override fun onCreate(savedInstanceState: Bundle?) { private var _binding: FragmentSubscriptionBinding? = null
private val binding get() = _binding!!
// Life Cycle
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = FragmentSubscriptionBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val cm = requireContext().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val cm = requireContext().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
@ -78,10 +94,6 @@ class SubscriptionFragment : BaseFragment(), SkuDetailsResponseListener, Purchas
} }
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_subscription, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initData() initData()
@ -99,6 +111,11 @@ class SubscriptionFragment : BaseFragment(), SkuDetailsResponseListener, Purchas
private fun initUI() { private fun initUI() {
val title = binding.title
val message = binding.message
val pager = binding.pager
val purchase = binding.purchase
val pageIndicator = binding.pageIndicator
val upgradeString = requireContext().getString(R.string.pro_upgrade) val upgradeString = requireContext().getString(R.string.pro_upgrade)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
@ -119,25 +136,25 @@ class SubscriptionFragment : BaseFragment(), SkuDetailsResponseListener, Purchas
} }
} }
this.title.text = ssb title.text = ssb
} else { } else {
this.title.text = upgradeString title.text = upgradeString
} }
if (showSessionMessage) { if (showSessionMessage) {
this.message.text = getString(R.string.iap_session_message) message.text = getString(R.string.iap_session_message)
} }
// Pager // Pager
// The pager adapter, which provides the pages to the view pager widget. // The pager adapter, which provides the pages to the view pager widget.
this.pagerAdapter = ScreenSlidePagerAdapter(parentFragmentManager) this.pagerAdapter = ScreenSlidePagerAdapter(parentFragmentManager)
this.pager.adapter = pagerAdapter pager.adapter = pagerAdapter
this.pager.addOnPageChangeListener(this) pager.addOnPageChangeListener(this)
this.purchase.isEnabled = false purchase.isEnabled = false
this.purchase.setOnClickListener { purchase.setOnClickListener {
this.selectedProduct?.let { this.selectedProduct?.let {
AppGuard.initiatePurchase(this.requireActivity(), it) AppGuard.initiatePurchase(this.requireActivity(), it)
@ -146,13 +163,13 @@ class SubscriptionFragment : BaseFragment(), SkuDetailsResponseListener, Purchas
} }
} }
val count = this.pager.adapter?.count ?: 0 val count = pager.adapter?.count ?: 0
for (i in 1..count) { for (i in 1..count) {
val view = View(requireContext()) val view = View(requireContext())
view.background = requireContext().getDrawable(R.drawable.circle_green) view.background = requireContext().getDrawable(R.drawable.circle_green)
val layoutParam = LinearLayout.LayoutParams(8.px, 8.px) val layoutParam = LinearLayout.LayoutParams(8.px, 8.px)
layoutParam.setMargins(6.px) layoutParam.setMargins(6.px)
this.pageIndicator.addView(view, layoutParam) pageIndicator.addView(view, layoutParam)
} }
this.updatePagerIndicators(0) this.updatePagerIndicators(0)
@ -210,10 +227,10 @@ class SubscriptionFragment : BaseFragment(), SkuDetailsResponseListener, Purchas
private fun updateUI() { private fun updateUI() {
this.selectedProduct?.let { this.selectedProduct?.let {
this.purchase.isEnabled = true binding.purchase.isEnabled = true
val perYearString = requireContext().getString(R.string.year_subscription) val perYearString = requireContext().getString(R.string.year_subscription)
val formattedPrice = it.price + " / " + perYearString val formattedPrice = it.price + " / " + perYearString
this.price.text = formattedPrice binding.price.text = formattedPrice
var freeTrialDays = 30 // initial, should be more, no less var freeTrialDays = 30 // initial, should be more, no less
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
@ -226,7 +243,7 @@ class SubscriptionFragment : BaseFragment(), SkuDetailsResponseListener, Purchas
} }
val formattedFreeTrial = val formattedFreeTrial =
"$freeTrialDays " + requireContext().getString(R.string.days) + " " + requireContext().getString(R.string.free_trial) "$freeTrialDays " + requireContext().getString(R.string.days) + " " + requireContext().getString(R.string.free_trial)
this.freetrial.text = formattedFreeTrial binding.freetrial.text = formattedFreeTrial
} ?: run { } ?: run {
Toast.makeText(requireContext(), R.string.contact_support, Toast.LENGTH_LONG).show() Toast.makeText(requireContext(), R.string.contact_support, Toast.LENGTH_LONG).show()
} }
@ -261,7 +278,7 @@ class SubscriptionFragment : BaseFragment(), SkuDetailsResponseListener, Purchas
} }
private fun updatePagerIndicators(position: Int) { private fun updatePagerIndicators(position: Int) {
this.pageIndicator.children.forEachIndexed { index, view -> binding.pageIndicator.children.forEachIndexed { index, view ->
val drawable = view.background val drawable = view.background
when (drawable) { when (drawable) {
is GradientDrawable -> { is GradientDrawable -> {

@ -7,8 +7,7 @@ import android.view.ViewGroup
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import io.realm.RealmResults import io.realm.RealmResults
import io.realm.kotlin.where import io.realm.kotlin.where
import kotlinx.android.synthetic.main.fragment_top_10.* import net.pokeranalytics.android.databinding.FragmentTop10Binding
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource
@ -43,10 +42,21 @@ class Top10Fragment : RealmFragment(), RowRepresentableDataSource, RowRepresenta
private var currentTab: Tab = Tab.CASH_GAMES private var currentTab: Tab = Tab.CASH_GAMES
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { private var _binding: FragmentTop10Binding? = null
super.onCreateView(inflater, container, savedInstanceState) private val binding get() = _binding!!
return inflater.inflate(R.layout.fragment_top_10, container, false)
} // Life Cycle
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentTop10Binding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -59,7 +69,10 @@ class Top10Fragment : RealmFragment(), RowRepresentableDataSource, RowRepresenta
*/ */
private fun initUI() { private fun initUI() {
dataListAdapter = RowRepresentableAdapter(this, this) val recyclerView = binding.recyclerView
val tabs = binding.tabs
dataListAdapter = RowRepresentableAdapter(this, this)
recyclerView.adapter = dataListAdapter recyclerView.adapter = dataListAdapter
setDisplayHomeAsUpEnabled(true) setDisplayHomeAsUpEnabled(true)

@ -6,8 +6,9 @@ import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.os.Bundle import android.os.Bundle
import android.view.* import android.view.*
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import kotlinx.android.synthetic.main.view_selected_filter.view.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -57,7 +58,11 @@ open class FilterableFragment : RealmFragment(),
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
parentActivity?.registerReceiver(updateFilterUIBroadcast, IntentFilter(INTENT_FILTER_UPDATE_FILTER_UI)) parentActivity?.registerReceiver(
updateFilterUIBroadcast, IntentFilter(
INTENT_FILTER_UPDATE_FILTER_UI
)
)
} }
override fun onDestroy() { override fun onDestroy() {
@ -65,7 +70,11 @@ open class FilterableFragment : RealmFragment(),
parentActivity?.unregisterReceiver(updateFilterUIBroadcast) parentActivity?.unregisterReceiver(updateFilterUIBroadcast)
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
setHasOptionsMenu(true) setHasOptionsMenu(true)
return super.onCreateView(inflater, container, savedInstanceState) return super.onCreateView(inflater, container, savedInstanceState)
} }
@ -82,9 +91,9 @@ open class FilterableFragment : RealmFragment(),
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
R.id.menu_item_filter -> { R.id.menu_item_filter -> {
manageFilters(this) manageFilters(this)
} }
} }
return super.onOptionsItemSelected(item) return super.onOptionsItemSelected(item)
} }
@ -119,9 +128,15 @@ open class FilterableFragment : RealmFragment(),
} }
view?.findViewById<ViewGroup>(R.id.selectedFilter)?.let { viewGroup -> view?.findViewById<ViewGroup>(R.id.selectedFilter)?.let { viewGroup ->
val layoutCurrentFilter = LayoutInflater.from(requireContext()).inflate(R.layout.view_selected_filter, viewGroup, false) val layoutCurrentFilter = LayoutInflater.from(requireContext()).inflate(
layoutCurrentFilter.filterName.text = filter.getDisplayName(requireContext()) R.layout.view_selected_filter,
layoutCurrentFilter.deselectFilter.setOnClickListener { viewGroup,
false
)
layoutCurrentFilter.findViewById<TextView>(R.id.filterName)?.text = filter.getDisplayName(
requireContext()
)
layoutCurrentFilter.findViewById<ImageView>(R.id.deselectFilter).setOnClickListener {
saveFilter(requireContext(), "") saveFilter(requireContext(), "")
} }

@ -5,8 +5,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import kotlinx.android.synthetic.main.fragment_loader.* import net.pokeranalytics.android.databinding.FragmentLoaderBinding
import net.pokeranalytics.android.R
class LoaderDialogFragment: DialogFragment() { class LoaderDialogFragment: DialogFragment() {
@ -31,15 +30,26 @@ class LoaderDialogFragment: DialogFragment() {
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { private var _binding: FragmentLoaderBinding? = null
return inflater.inflate(R.layout.fragment_loader, container, false) private val binding get() = _binding!!
}
// Life Cycle
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = FragmentLoaderBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
arguments?.let {bundle -> arguments?.let {bundle ->
if (bundle.containsKey(ARGUMENT_MESSAGE_RES_ID)) { if (bundle.containsKey(ARGUMENT_MESSAGE_RES_ID)) {
loadingMessage.text = getString(bundle.getInt(ARGUMENT_MESSAGE_RES_ID)) binding.loadingMessage.text = getString(bundle.getInt(ARGUMENT_MESSAGE_RES_ID))
} }
} }
} }

@ -4,8 +4,8 @@ import android.os.Bundle
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 kotlinx.android.synthetic.main.fragment_screen_slide_page.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentScreenSlidePageBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
@ -31,20 +31,29 @@ class ScreenSlidePageFragment : BaseFragment() {
} }
override fun onCreateView( private var _binding: FragmentScreenSlidePageBinding? = null
inflater: LayoutInflater, private val binding get() = _binding!!
container: ViewGroup?,
savedInstanceState: Bundle? // Life Cycle
): View = inflater.inflate(R.layout.fragment_screen_slide_page, container, false)
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = FragmentScreenSlidePageBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val bundle = arguments ?: throw PAIllegalStateException("No bundle found") val bundle = arguments ?: throw PAIllegalStateException("No bundle found")
this.icon.setImageResource(bundle.getInt(BundleKey.ICON.key)) binding.icon.setImageResource(bundle.getInt(BundleKey.ICON.key))
this.title.text = requireContext().getString(bundle.getInt(BundleKey.TITLE.key)) binding.title.text = requireContext().getString(bundle.getInt(BundleKey.TITLE.key))
this.description.text = requireContext().getString(bundle.getInt(BundleKey.DESCRIPTION.key)) binding.description.text = requireContext().getString(bundle.getInt(BundleKey.DESCRIPTION.key))
} }
/** /**

@ -4,29 +4,41 @@ import android.os.Bundle
import android.text.InputType import android.text.InputType
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import androidx.core.widget.addTextChangedListener import androidx.core.widget.addTextChangedListener
import kotlinx.android.synthetic.main.bottom_sheet_double_edit_text.* import net.pokeranalytics.android.databinding.BottomSheetDoubleEditTextBinding
import kotlinx.android.synthetic.main.fragment_bottom_sheet.view.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorException import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorException
import net.pokeranalytics.android.util.extensions.round import net.pokeranalytics.android.util.extensions.round
class BottomSheetDoubleEditTextFragment : BottomSheetFragment() { class BottomSheetDoubleEditTextFragment : BottomSheetFragment() {
private var _binding: BottomSheetDoubleEditTextBinding? = null
private val binding get() = _binding!!
override fun getChildView(inflater: LayoutInflater, container: ViewGroup): View? {
_binding = BottomSheetDoubleEditTextBinding.inflate(inflater, container, true)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initData() initData()
initUI() initUI()
} }
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
if (this.model.isEditingBlinds) { if (this.model.isEditingBlinds) {
editText2.requestFocus() binding.editText2.requestFocus()
} else { } else {
editText.requestFocus() binding.editText.requestFocus()
} }
} }
@ -47,56 +59,47 @@ class BottomSheetDoubleEditTextFragment : BottomSheetFragment() {
throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor inconsistency") throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor inconsistency")
} }
// values.add(0, "") data[0].hintResId?.let { binding.editText.hint = getString(it) }
// values.add(1, "") binding.editText.inputType = data[0].inputType ?: InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
data[1].hintResId?.let { binding.editText2.hint = getString(it) }
LayoutInflater.from(requireContext()) binding.editText2.inputType = data[1].inputType ?: InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
.inflate(R.layout.bottom_sheet_double_edit_text, view?.bottomSheetContainer, true)
// values[0] = (data[0].defaultValue ?: "").toString()
// values[1] = (data[1].defaultValue ?: "").toString()
data[0].hintResId?.let { editText.hint = getString(it) }
editText.inputType = data[0].inputType ?: InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
data[1].hintResId?.let { editText2.hint = getString(it) }
editText2.inputType = data[1].inputType ?: InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
if (this.model.valueAsHint) { if (this.model.valueAsHint) {
this.model.stringValue?.let { this.model.stringValue?.let {
if (it.isNotBlank()) { if (it.isNotBlank()) {
editText.hint = it binding.editText.hint = it
} }
} }
this.model.secondStringValue?.let { this.model.secondStringValue?.let {
if (it.isNotBlank()) { if (it.isNotBlank()) {
editText2.hint = it binding.editText2.hint = it
} }
} }
// if (this.viewModel.stringValue?.isNotBlank()) { editText.hint = values[0] } // if (this.viewModel.stringValue?.isNotBlank()) { editText.hint = values[0] }
// if (values[1].isNotBlank()) { editText2.hint = values[1] } // if (values[1].isNotBlank()) { editText2.hint = values[1] }
} else { } else {
editText.setText(this.model.stringValue) binding.editText.setText(this.model.stringValue)
editText2.setText(this.model.secondStringValue) binding.editText2.setText(this.model.secondStringValue)
} }
editText.addTextChangedListener { binding.editText.addTextChangedListener {
this.model.stringValue = it?.toString() this.model.stringValue = it?.toString()
} }
editText2.addTextChangedListener { binding.editText2.addTextChangedListener {
this.model.secondStringValue = it?.toString() this.model.secondStringValue = it?.toString()
if (this.model.isEditingBlinds) { if (this.model.isEditingBlinds) {
try { try {
val bigBlind = this.model.secondStringValue?.toDouble() ?: 0.0 val bigBlind = this.model.secondStringValue?.toDouble() ?: 0.0
editText.setText((bigBlind / 2.0).round()) binding.editText.setText((bigBlind / 2.0).round())
} catch (e: Exception) { } catch (e: Exception) {
editText.setText("") binding.editText.setText("")
} }
} }
} }
editText2.setOnEditorActionListener { _, actionId, _ -> binding.editText2.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) { if (actionId == EditorInfo.IME_ACTION_DONE) {
this.onRowValueChanged() this.onRowValueChanged()
// this.delegate.onRowValueChanged(values, row) // this.delegate.onRowValueChanged(values, row)

@ -4,38 +4,48 @@ import android.os.Bundle
import android.text.InputType import android.text.InputType
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import androidx.core.widget.addTextChangedListener import androidx.core.widget.addTextChangedListener
import kotlinx.android.synthetic.main.bottom_sheet_edit_text.* import net.pokeranalytics.android.databinding.BottomSheetEditTextBinding
import kotlinx.android.synthetic.main.fragment_bottom_sheet.view.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorException import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorException
class BottomSheetEditTextFragment : BottomSheetFragment() { class BottomSheetEditTextFragment : BottomSheetFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { private var _binding: BottomSheetEditTextBinding? = null
private val binding get() = _binding!!
override fun getChildView(inflater: LayoutInflater, container: ViewGroup): View? {
_binding = BottomSheetEditTextBinding.inflate(inflater, container, true)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initUI() initUI()
} }
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
editText.requestFocus() binding.editText.requestFocus()
} }
/** /**
* Init UI * Init UI
*/ */
private fun initUI() { private fun initUI() {
val editText = binding.editText
val data = getDescriptors() ?: throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor not found for $this") val data = getDescriptors() ?: throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor not found for $this")
if (data.size != 1) { if (data.size != 1) {
throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor inconsistency") throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor inconsistency")
} }
LayoutInflater.from(requireContext()).inflate(R.layout.bottom_sheet_edit_text, view?.bottomSheetContainer, true)
data[0].hintResId?.let { editText.hint = getString(it) } data[0].hintResId?.let { editText.hint = getString(it) }
editText.inputType = data[0].inputType ?: InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES editText.inputType = data[0].inputType ?: InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
editText.addTextChangedListener { editText.addTextChangedListener {

@ -4,14 +4,27 @@ import android.os.Bundle
import android.text.InputType import android.text.InputType
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.core.widget.addTextChangedListener import androidx.core.widget.addTextChangedListener
import kotlinx.android.synthetic.main.bottom_sheet_edit_text_multi_lines.* import net.pokeranalytics.android.databinding.BottomSheetEditTextMultiLinesBinding
import kotlinx.android.synthetic.main.fragment_bottom_sheet.view.*
import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorException import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorException
class BottomSheetEditTextMultiLinesFragment : BottomSheetFragment() { class BottomSheetEditTextMultiLinesFragment : BottomSheetFragment() {
private var _binding: BottomSheetEditTextMultiLinesBinding? = null
private val binding get() = _binding!!
override fun getChildView(inflater: LayoutInflater, container: ViewGroup): View? {
_binding = BottomSheetEditTextMultiLinesBinding.inflate(inflater, container, true)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initUI() initUI()
@ -19,20 +32,19 @@ class BottomSheetEditTextMultiLinesFragment : BottomSheetFragment() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
editText.requestFocus() binding.editText.requestFocus()
} }
/** /**
* Init UI * Init UI
*/ */
private fun initUI() { private fun initUI() {
val editText = binding.editText
val data = getDescriptors() ?: throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor not found") val data = getDescriptors() ?: throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor not found")
if (data.size != 1) { if (data.size != 1) {
throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor inconsistency") throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor inconsistency")
} }
LayoutInflater.from(requireContext()).inflate(net.pokeranalytics.android.R.layout.bottom_sheet_edit_text_multi_lines, view?.bottomSheetContainer, true)
data[0].hintResId?.let { editText.hint = getString(it) } data[0].hintResId?.let { editText.hint = getString(it) }
editText.inputType = data[0].inputType ?: InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES editText.inputType = data[0].inputType ?: InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
editText.addTextChangedListener { this.model.stringValue = it?.toString() } editText.addTextChangedListener { this.model.stringValue = it?.toString() }

@ -9,11 +9,10 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowManager import android.view.WindowManager
import androidx.appcompat.view.ContextThemeWrapper
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kotlinx.android.synthetic.main.fragment_bottom_sheet.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentBottomSheetBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.ui.activity.components.BaseActivity import net.pokeranalytics.android.ui.activity.components.BaseActivity
@ -46,6 +45,9 @@ open class BottomSheetFragment : BottomSheetDialogFragment() {
protected lateinit var dataAdapter: RowRepresentableAdapter protected lateinit var dataAdapter: RowRepresentableAdapter
private var _binding: FragmentBottomSheetBinding? = null
private val binding get() = _binding!!
companion object { companion object {
private var config: BottomSheetConfig? = null private var config: BottomSheetConfig? = null
@ -91,11 +93,22 @@ open class BottomSheetFragment : BottomSheetDialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
//TODO: When dependency 'com.google.android.material:material:1.1.0' will be available in stable version, upgrade and remove that //TODO: When dependency 'com.google.android.material:material:1.1.0' will be available in stable version, upgrade and remove that
val contextThemeWrapper = ContextThemeWrapper(activity, R.style.PokerAnalyticsTheme) activity?.setTheme(R.style.PokerAnalyticsTheme)
return inflater.cloneInContext(contextThemeWrapper).inflate(R.layout.fragment_bottom_sheet, container, false) _binding = FragmentBottomSheetBinding.inflate(inflater, container, false)
binding.bottomSheetContainer.addView(getChildView(inflater, binding.root))
return binding.root
} }
private fun initModel() { open fun getChildView(inflater: LayoutInflater, container: ViewGroup): View? {
return null
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
private fun initModel() {
val row = config?.row val row = config?.row
?: (requireActivity() as? BaseActivity)?.bottomSheetViewModel?.rowRepresentable ?: (requireActivity() as? BaseActivity)?.bottomSheetViewModel?.rowRepresentable
@ -174,6 +187,7 @@ open class BottomSheetFragment : BottomSheetDialogFragment() {
private fun initUI() { private fun initUI() {
val row = this.model.row val row = this.model.row
val bottomSheetToolbar = binding.bottomSheetToolbar
bottomSheetToolbar.title = row.localizedTitle(requireContext()) bottomSheetToolbar.title = row.localizedTitle(requireContext())
bottomSheetToolbar.inflateMenu(R.menu.toolbar_bottom_sheet) bottomSheetToolbar.inflateMenu(R.menu.toolbar_bottom_sheet)
bottomSheetToolbar.setOnMenuItemClickListener { bottomSheetToolbar.setOnMenuItemClickListener {

@ -3,10 +3,9 @@ package net.pokeranalytics.android.ui.fragment.components.bottomsheet
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.bottom_sheet_list.* import net.pokeranalytics.android.databinding.BottomSheetListBinding
import kotlinx.android.synthetic.main.fragment_bottom_sheet.view.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.ui.adapter.LiveRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.LiveRowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
@ -16,6 +15,19 @@ import net.pokeranalytics.android.ui.view.RowViewType
open class BottomSheetListFragment : BottomSheetFragment(), LiveRowRepresentableDataSource, RowRepresentableDelegate { open class BottomSheetListFragment : BottomSheetFragment(), LiveRowRepresentableDataSource, RowRepresentableDelegate {
private var _binding: BottomSheetListBinding? = null
private val binding get() = _binding!!
override fun getChildView(inflater: LayoutInflater, container: ViewGroup): View? {
_binding = BottomSheetListBinding.inflate(inflater, container, true)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun adapterRows(): List<RowRepresentable>? { override fun adapterRows(): List<RowRepresentable>? {
return this.model.realmData return this.model.realmData
} }
@ -82,13 +94,11 @@ open class BottomSheetListFragment : BottomSheetFragment(), LiveRowRepresentable
* Init UI * Init UI
*/ */
open fun initUI() { open fun initUI() {
LayoutInflater.from(requireContext()).inflate(R.layout.bottom_sheet_list, view?.bottomSheetContainer, true)
val viewManager = LinearLayoutManager(requireContext()) val viewManager = LinearLayoutManager(requireContext())
val dataAdapter = RowRepresentableAdapter(this, this) val dataAdapter = RowRepresentableAdapter(this, this)
this.dataAdapter = dataAdapter this.dataAdapter = dataAdapter
recyclerView.apply { binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
adapter = dataAdapter adapter = dataAdapter

@ -3,12 +3,11 @@ package net.pokeranalytics.android.ui.fragment.components.bottomsheet
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.core.view.get import androidx.core.view.get
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import kotlinx.android.synthetic.main.bottom_sheet_game_list.* import net.pokeranalytics.android.databinding.BottomSheetGameListBinding
import kotlinx.android.synthetic.main.fragment_bottom_sheet.view.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.Limit import net.pokeranalytics.android.model.Limit
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.extensions.px import net.pokeranalytics.android.ui.extensions.px
@ -20,6 +19,19 @@ import net.pokeranalytics.android.ui.view.RowRepresentable
*/ */
class BottomSheetListGameFragment : BottomSheetListFragment() { class BottomSheetListGameFragment : BottomSheetListFragment() {
private var _binding: BottomSheetGameListBinding? = null
private val binding get() = _binding!!
override fun getChildView(inflater: LayoutInflater, container: ViewGroup): View? {
_binding = BottomSheetGameListBinding.inflate(inflater, container, true)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initUI() initUI()
@ -41,8 +53,7 @@ class BottomSheetListGameFragment : BottomSheetListFragment() {
* Init UI * Init UI
*/ */
override fun initUI() { override fun initUI() {
LayoutInflater.from(requireContext()).inflate(R.layout.bottom_sheet_game_list, view?.bottomSheetContainer, true) val chipGroup = binding.chipGroup
val limit = this.model.limit val limit = this.model.limit
this.model.someValues.add(0, limit) this.model.someValues.add(0, limit)
@ -71,7 +82,7 @@ class BottomSheetListGameFragment : BottomSheetListFragment() {
val dataAdapter = RowRepresentableAdapter(this, this) val dataAdapter = RowRepresentableAdapter(this, this)
this.dataAdapter = dataAdapter this.dataAdapter = dataAdapter
recyclerView2.apply { binding.recyclerView2.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager2 layoutManager = viewManager2
adapter = dataAdapter adapter = dataAdapter

@ -2,7 +2,11 @@ package net.pokeranalytics.android.ui.fragment.components.bottomsheet
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import io.realm.RealmModel import io.realm.RealmModel
import net.pokeranalytics.android.databinding.BottomSheetDoubleEditTextBinding
import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.ui.modules.data.EditableDataActivity import net.pokeranalytics.android.ui.modules.data.EditableDataActivity
import net.pokeranalytics.android.ui.activity.components.BaseActivity import net.pokeranalytics.android.ui.activity.components.BaseActivity
@ -14,6 +18,19 @@ import net.pokeranalytics.android.ui.view.RowViewType
*/ */
open class BottomSheetMultiSelectionFragment : BottomSheetListFragment() { open class BottomSheetMultiSelectionFragment : BottomSheetListFragment() {
private var _binding: BottomSheetDoubleEditTextBinding? = null
private val binding get() = _binding!!
override fun getChildView(inflater: LayoutInflater, container: ViewGroup): View? {
_binding = BottomSheetDoubleEditTextBinding.inflate(inflater, container, true)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun viewTypeForPosition(position: Int): Int { override fun viewTypeForPosition(position: Int): Int {
return RowViewType.TITLE_CHECK.ordinal return RowViewType.TITLE_CHECK.ordinal
} }

@ -4,17 +4,29 @@ import android.os.Bundle
import android.text.InputType import android.text.InputType
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import androidx.core.widget.addTextChangedListener import androidx.core.widget.addTextChangedListener
import kotlinx.android.synthetic.main.bottom_sheet_edit_text.* import net.pokeranalytics.android.databinding.BottomSheetEditTextBinding
import kotlinx.android.synthetic.main.fragment_bottom_sheet.view.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorException import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorException
import java.text.NumberFormat import java.text.NumberFormat
class BottomSheetNumericTextFragment : BottomSheetFragment() { class BottomSheetNumericTextFragment : BottomSheetFragment() {
private var _binding: BottomSheetEditTextBinding? = null
private val binding get() = _binding!!
override fun getChildView(inflater: LayoutInflater, container: ViewGroup): View? {
_binding = BottomSheetEditTextBinding.inflate(inflater, container, true)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initUI() initUI()
@ -22,20 +34,19 @@ class BottomSheetNumericTextFragment : BottomSheetFragment() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
editText.requestFocus() binding.editText.requestFocus()
} }
/** /**
* Init UI * Init UI
*/ */
private fun initUI() { private fun initUI() {
val editText = binding.editText
val data = getDescriptors()?:throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor not found") val data = getDescriptors()?:throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor not found")
if (data.size != 1) { if (data.size != 1) {
throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor inconsistency") throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor inconsistency")
} }
LayoutInflater.from(requireContext()).inflate(R.layout.bottom_sheet_edit_text, view?.bottomSheetContainer, true)
data[0].hintResId?.let { editText.hint = getString(it) } data[0].hintResId?.let { editText.hint = getString(it) }
editText.inputType = data[0].inputType ?: InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES editText.inputType = data[0].inputType ?: InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES

@ -3,10 +3,9 @@ package net.pokeranalytics.android.ui.fragment.components.bottomsheet
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.bottom_sheet_list.* import net.pokeranalytics.android.databinding.BottomSheetListBinding
import kotlinx.android.synthetic.main.fragment_bottom_sheet.view.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
@ -15,10 +14,20 @@ import net.pokeranalytics.android.ui.view.RowRepresentable
class BottomSheetStaticListFragment : BottomSheetFragment(), StaticRowRepresentableDataSource, class BottomSheetStaticListFragment : BottomSheetFragment(), StaticRowRepresentableDataSource,
RowRepresentableDelegate { RowRepresentableDelegate {
// private var staticRows: List<RowRepresentable> = emptyList() private var _binding: BottomSheetListBinding? = null
// private lateinit var dataAdapter: RowRepresentableAdapter private val binding get() = _binding!!
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun getChildView(inflater: LayoutInflater, container: ViewGroup): View? {
_binding = BottomSheetListBinding.inflate(inflater, container, true)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initUI() initUI()
} }
@ -45,13 +54,12 @@ class BottomSheetStaticListFragment : BottomSheetFragment(), StaticRowRepresenta
* Init UI * Init UI
*/ */
private fun initUI() { private fun initUI() {
LayoutInflater.from(requireContext()).inflate(R.layout.bottom_sheet_list, view?.bottomSheetContainer, true)
val viewManager = LinearLayoutManager(requireContext()) val viewManager = LinearLayoutManager(requireContext())
val dataAdapter = RowRepresentableAdapter(this, this) val dataAdapter = RowRepresentableAdapter(this, this)
this.dataAdapter = dataAdapter this.dataAdapter = dataAdapter
recyclerView.apply { binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
adapter = dataAdapter adapter = dataAdapter

@ -4,11 +4,10 @@ import android.os.Bundle
import android.text.InputType import android.text.InputType
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import androidx.core.widget.addTextChangedListener import androidx.core.widget.addTextChangedListener
import kotlinx.android.synthetic.main.bottom_sheet_sum.* import net.pokeranalytics.android.databinding.BottomSheetSumBinding
import kotlinx.android.synthetic.main.fragment_bottom_sheet.view.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorException import net.pokeranalytics.android.exceptions.RowRepresentableEditDescriptorException
import net.pokeranalytics.android.util.extensions.round import net.pokeranalytics.android.util.extensions.round
import net.pokeranalytics.android.util.extensions.toCurrency import net.pokeranalytics.android.util.extensions.toCurrency
@ -17,14 +16,27 @@ import java.text.NumberFormat
class BottomSheetSumFragment : BottomSheetFragment() { class BottomSheetSumFragment : BottomSheetFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { private var _binding: BottomSheetSumBinding? = null
private val binding get() = _binding!!
override fun getChildView(inflater: LayoutInflater, container: ViewGroup): View? {
_binding = BottomSheetSumBinding.inflate(inflater, container, true)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initUI() initUI()
} }
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
editText.requestFocus() binding.editText.requestFocus()
} }
@ -32,11 +44,16 @@ class BottomSheetSumFragment : BottomSheetFragment() {
* Init UI * Init UI
*/ */
private fun initUI() { private fun initUI() {
val currentValue = binding.currentValue
val editText = binding.editText
val editText2 = binding.editText2
val button1 = binding.button1
val button2 = binding.button2
val data = getDescriptors()?:throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor not found") val data = getDescriptors()?:throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor not found")
if (data.size != 5) { if (data.size != 5) {
throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor inconsistency") throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor inconsistency")
} }
LayoutInflater.from(requireContext()).inflate(R.layout.bottom_sheet_sum, view?.bottomSheetContainer, true)
if (data.size == 5) { if (data.size == 5) {

@ -3,10 +3,9 @@ package net.pokeranalytics.android.ui.fragment.components.bottomsheet
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import kotlinx.android.synthetic.main.bottom_sheet_grid.* import net.pokeranalytics.android.databinding.BottomSheetGridBinding
import kotlinx.android.synthetic.main.fragment_bottom_sheet.view.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.TableSize import net.pokeranalytics.android.model.TableSize
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
@ -17,9 +16,20 @@ import net.pokeranalytics.android.ui.view.RowRepresentable
class BottomSheetTableSizeGridFragment : BottomSheetFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { class BottomSheetTableSizeGridFragment : BottomSheetFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate {
// private lateinit var dataAdapter: RowRepresentableAdapter private var _binding: BottomSheetGridBinding? = null
private val binding get() = _binding!!
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun getChildView(inflater: LayoutInflater, container: ViewGroup): View? {
_binding = BottomSheetGridBinding.inflate(inflater, container, true)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initUI() initUI()
} }
@ -34,8 +44,6 @@ class BottomSheetTableSizeGridFragment : BottomSheetFragment(), StaticRowReprese
* Init UI * Init UI
*/ */
private fun initUI() { private fun initUI() {
LayoutInflater.from(requireContext())
.inflate(R.layout.bottom_sheet_grid, view?.bottomSheetContainer, true)
val viewManager = GridLayoutManager(requireContext(), 3) val viewManager = GridLayoutManager(requireContext(), 3)
val dataAdapter = RowRepresentableAdapter(this, this) val dataAdapter = RowRepresentableAdapter(this, this)
@ -45,7 +53,7 @@ class BottomSheetTableSizeGridFragment : BottomSheetFragment(), StaticRowReprese
val spacing = 2.px val spacing = 2.px
val includeEdge = false val includeEdge = false
recyclerView.apply { binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
adapter = dataAdapter adapter = dataAdapter

@ -5,8 +5,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import kotlinx.android.synthetic.main.fragment_report_details.* import net.pokeranalytics.android.databinding.FragmentReportDetailsBinding
import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.adapter.ReportPagerAdapter import net.pokeranalytics.android.ui.adapter.ReportPagerAdapter
class ComparisonReportFragment : AbstractReportFragment() { class ComparisonReportFragment : AbstractReportFragment() {
@ -21,10 +20,21 @@ class ComparisonReportFragment : AbstractReportFragment() {
} }
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { private var _binding: FragmentReportDetailsBinding? = null
super.onCreateView(inflater, container, savedInstanceState) private val binding get() = _binding!!
return inflater.inflate(R.layout.fragment_report_details, container, false)
} // Life Cycle
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentReportDetailsBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -36,6 +46,9 @@ class ComparisonReportFragment : AbstractReportFragment() {
*/ */
private fun initUI() { private fun initUI() {
val viewPager = binding.viewPager
val tabs = binding.tabs
viewPager.adapter = ReportPagerAdapter(requireContext(), requireActivity().supportFragmentManager, this.reportViewModel) viewPager.adapter = ReportPagerAdapter(requireContext(), requireActivity().supportFragmentManager, this.reportViewModel)
// setDisplayHomeAsUpEnabled(true) // setDisplayHomeAsUpEnabled(true)

@ -7,7 +7,6 @@ import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import io.realm.Realm import io.realm.Realm
import kotlinx.android.synthetic.main.fragment_composable_table_report.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async import kotlinx.coroutines.async
@ -17,6 +16,7 @@ import net.pokeranalytics.android.calculus.Calculator
import net.pokeranalytics.android.calculus.ComputableGroup import net.pokeranalytics.android.calculus.ComputableGroup
import net.pokeranalytics.android.calculus.Report import net.pokeranalytics.android.calculus.Report
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.databinding.FragmentComposableTableReportBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.realm.ComputableResult import net.pokeranalytics.android.model.realm.ComputableResult
import net.pokeranalytics.android.ui.activity.components.ReportActivity import net.pokeranalytics.android.ui.activity.components.ReportActivity
@ -39,34 +39,43 @@ open class ComposableTableReportFragment : RealmFragment(), StaticRowRepresentab
// override val coroutineContext: CoroutineContext // override val coroutineContext: CoroutineContext
// get() = Dispatchers.Main // get() = Dispatchers.Main
private var rowRepresentables: ArrayList<RowRepresentable> = ArrayList() companion object {
/**
* Create new instance
*/
fun newInstance(report: Report? = null): ComposableTableReportFragment {
val fragment = ComposableTableReportFragment()
fragment.report = report
val bundle = Bundle()
fragment.arguments = bundle
return fragment
}
}
private var rowRepresentables: ArrayList<RowRepresentable> = ArrayList()
private var statsAdapter: RowRepresentableAdapter? = null private var statsAdapter: RowRepresentableAdapter? = null
var report: Report? = null var report: Report? = null
private var hasComputationInProgress: Boolean = false private var hasComputationInProgress: Boolean = false
companion object { private var _binding: FragmentComposableTableReportBinding? = null
private val binding get() = _binding!!
/**
* Create new instance
*/
fun newInstance(report: Report? = null): ComposableTableReportFragment {
val fragment = ComposableTableReportFragment()
fragment.report = report
val bundle = Bundle()
fragment.arguments = bundle
return fragment
}
}
// Life Cycle // Life Cycle
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onDestroyView() {
super.onCreateView(inflater, container, savedInstanceState) super.onDestroyView()
return inflater.inflate(R.layout.fragment_composable_table_report, container, false) _binding = null
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentComposableTableReportBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -126,7 +135,7 @@ open class ComposableTableReportFragment : RealmFragment(), StaticRowRepresentab
open fun initUI() { open fun initUI() {
val viewManager = LinearLayoutManager(requireContext()) val viewManager = LinearLayoutManager(requireContext())
recyclerView.apply { binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
adapter = statsAdapter adapter = statsAdapter

@ -11,15 +11,19 @@ import com.github.mikephil.charting.data.LineDataSet
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup import com.google.android.material.chip.ChipGroup
import io.realm.Realm import io.realm.Realm
import kotlinx.android.synthetic.main.fragment_progress_report.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.calcul.barEntries
import net.pokeranalytics.android.calcul.defaultStatEntries
import net.pokeranalytics.android.calcul.durationEntries
import net.pokeranalytics.android.calcul.lineEntries
import net.pokeranalytics.android.calculus.AggregationType import net.pokeranalytics.android.calculus.AggregationType
import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.Calculator
import net.pokeranalytics.android.calculus.Report import net.pokeranalytics.android.calculus.Report
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.databinding.FragmentProgressReportBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.combined import net.pokeranalytics.android.model.combined
import net.pokeranalytics.android.ui.extensions.ChipGroupExtension import net.pokeranalytics.android.ui.extensions.ChipGroupExtension
@ -27,6 +31,7 @@ import net.pokeranalytics.android.ui.extensions.hideWithAnimation
import net.pokeranalytics.android.ui.extensions.px import net.pokeranalytics.android.ui.extensions.px
import net.pokeranalytics.android.ui.extensions.showWithAnimation import net.pokeranalytics.android.ui.extensions.showWithAnimation
import net.pokeranalytics.android.ui.fragment.GraphFragment import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.graph.Graph
import timber.log.Timber import timber.log.Timber
import java.util.* import java.util.*
@ -38,7 +43,7 @@ class ProgressReportFragment : AbstractReportFragment() {
/** /**
* Creates new instance * Creates new instance
*/ */
fun newInstance(style: GraphFragment.Style? = null): ProgressReportFragment { fun newInstance(style: Graph.Style? = null): ProgressReportFragment {
val fragment = ProgressReportFragment() val fragment = ProgressReportFragment()
val bundle = Bundle() val bundle = Bundle()
style?.let { style?.let {
@ -53,10 +58,21 @@ class ProgressReportFragment : AbstractReportFragment() {
private var reports: MutableMap<AggregationType, Report> = EnumMap(AggregationType::class.java) private var reports: MutableMap<AggregationType, Report> = EnumMap(AggregationType::class.java)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { private var _binding: FragmentProgressReportBinding? = null
super.onCreateView(inflater, container, savedInstanceState) private val binding get() = _binding!!
return inflater.inflate(R.layout.fragment_progress_report, container, false)
} // Life Cycle
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentProgressReportBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -68,9 +84,10 @@ class ProgressReportFragment : AbstractReportFragment() {
*/ */
private fun initUI() { private fun initUI() {
val chipGroup = binding.chipGroup
val fragmentManager = parentActivity?.supportFragmentManager val fragmentManager = parentActivity?.supportFragmentManager
val fragmentTransaction = fragmentManager?.beginTransaction() val fragmentTransaction = fragmentManager?.beginTransaction()
this.graphFragment = GraphFragment.newInstance(GraphFragment.Style.LINE) this.graphFragment = GraphFragment.newInstance(Graph.Style.LINE)
fragmentTransaction?.add(R.id.graphContainer, this.graphFragment) fragmentTransaction?.add(R.id.graphContainer, this.graphFragment)
fragmentTransaction?.commit() fragmentTransaction?.commit()
@ -92,14 +109,14 @@ class ProgressReportFragment : AbstractReportFragment() {
chip.text = requireContext().getString(type.resId) chip.text = requireContext().getString(type.resId)
chip.chipStartPadding = 8f.px chip.chipStartPadding = 8f.px
chip.chipEndPadding = 8f.px chip.chipEndPadding = 8f.px
this.chipGroup.addView(chip) chipGroup.addView(chip)
} }
this.chipGroup.isVisible = this.reportViewModel.showAggregationChoices chipGroup.isVisible = this.reportViewModel.showAggregationChoices
this.chipGroup.isSingleSelection = true chipGroup.isSingleSelection = true
this.chipGroup.check(0) chipGroup.check(0)
this.chipGroup.setOnCheckedChangeListener(object : ChipGroupExtension.SingleSelectionOnCheckedListener() { chipGroup.setOnCheckedChangeListener(object : ChipGroupExtension.SingleSelectionOnCheckedListener() {
override fun onCheckedChanged(group: ChipGroup, checkedId: Int) { override fun onCheckedChanged(group: ChipGroup, checkedId: Int) {
super.onCheckedChanged(group, checkedId) super.onCheckedChanged(group, checkedId)
@ -136,6 +153,9 @@ class ProgressReportFragment : AbstractReportFragment() {
*/ */
private fun launchStatComputation(aggregationType: AggregationType) { private fun launchStatComputation(aggregationType: AggregationType) {
val graphContainer = binding.graphContainer
val progressBar = binding.progressBar
graphContainer.hideWithAnimation() graphContainer.hideWithAnimation()
progressBar.showWithAnimation() progressBar.showWithAnimation()
@ -188,11 +208,11 @@ class ProgressReportFragment : AbstractReportFragment() {
when (ds) { when (ds) {
is LineDataSet -> { is LineDataSet -> {
this.reportViewModel.setLineDataSet(ds) this.reportViewModel.setLineDataSet(ds)
graphFragment.reload(GraphFragment.Style.LINE) graphFragment.reload(Graph.Style.LINE)
} }
is BarDataSet -> { is BarDataSet -> {
this.reportViewModel.setBarDataSet(ds) this.reportViewModel.setBarDataSet(ds)
graphFragment.reload(GraphFragment.Style.BAR) graphFragment.reload(Graph.Style.BAR)
} }
else -> throw PAIllegalStateException("unmanaged data set") else -> throw PAIllegalStateException("unmanaged data set")
} }

@ -5,11 +5,10 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentTableReportBinding
class TableReportFragment : AbstractReportFragment() { class TableReportFragment : AbstractReportFragment() {
private lateinit var tableReportFragment: ComposableTableReportFragment
companion object { companion object {
fun newInstance(): TableReportFragment { fun newInstance(): TableReportFragment {
@ -20,10 +19,23 @@ class TableReportFragment : AbstractReportFragment() {
} }
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { private lateinit var tableReportFragment: ComposableTableReportFragment
super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_table_report, container, false) private var _binding: FragmentTableReportBinding? = null
} private val binding get() = _binding!!
// Life Cycle
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentTableReportBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)

@ -8,15 +8,10 @@ import com.github.mikephil.charting.charts.BarChart
import com.github.mikephil.charting.charts.BarLineChartBase import com.github.mikephil.charting.charts.BarLineChartBase
import com.github.mikephil.charting.components.XAxis import com.github.mikephil.charting.components.XAxis
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.AxisFormatting
import net.pokeranalytics.android.model.utils.CrashLogging import net.pokeranalytics.android.model.utils.CrashLogging
import net.pokeranalytics.android.ui.extensions.px import net.pokeranalytics.android.ui.extensions.px
enum class AxisFormatting {
DEFAULT,
X_DURATION,
Y_DURATION,
}
fun BarLineChartBase<*>.setStyle( fun BarLineChartBase<*>.setStyle(
small: Boolean, small: Boolean,
axisFormatting: AxisFormatting = AxisFormatting.DEFAULT, axisFormatting: AxisFormatting = AxisFormatting.DEFAULT,

@ -1,13 +1,19 @@
package net.pokeranalytics.android.ui.graph package net.pokeranalytics.android.ui.graph
import android.content.Context import android.content.Context
import com.github.mikephil.charting.data.Entry
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.view.DefaultLegendValues import net.pokeranalytics.android.ui.view.DefaultLegendValues
import net.pokeranalytics.android.ui.view.LegendContent import net.pokeranalytics.android.ui.view.LegendContent
import net.pokeranalytics.android.util.TextFormat import net.pokeranalytics.android.util.TextFormat
interface Graph {
enum class Style {
LINE,
BAR,
MULTILINE,
}
}
interface GraphUnderlyingEntry { interface GraphUnderlyingEntry {
fun entryTitle(context: Context): String fun entryTitle(context: Context): String
@ -15,14 +21,14 @@ interface GraphUnderlyingEntry {
fun legendValues( fun legendValues(
stat: Stat, stat: Stat,
entry: Entry, total: Double,
style: GraphFragment.Style, style: Graph.Style,
groupName: String, groupName: String,
context: Context context: Context
): LegendContent { ): LegendContent {
val leftName = stat.localizedTitle(context) val leftName = stat.localizedTitle(context)
val totalStatValue = stat.textFormat(entry.y.toDouble(), currency = null) val totalStatValue = stat.textFormat(total, currency = null)
return if (stat.legendHideRightValue) { return if (stat.legendHideRightValue) {
DefaultLegendValues(this.entryTitle(context), totalStatValue, leftName = leftName) DefaultLegendValues(this.entryTitle(context), totalStatValue, leftName = leftName)

@ -5,12 +5,12 @@ import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.* import android.view.*
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.fragment_bankroll.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.ComputedStat import net.pokeranalytics.android.calculus.ComputedStat
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.calculus.bankroll.BankrollReport import net.pokeranalytics.android.calculus.bankroll.BankrollReport
import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager
import net.pokeranalytics.android.databinding.FragmentBankrollDetailsBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.model.realm.Bankroll
@ -47,11 +47,16 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc
private var bankrollDetailsMenu: Menu? = null private var bankrollDetailsMenu: Menu? = null
private var _binding: FragmentBankrollDetailsBinding? = null
private val binding get() = _binding!!
// Life Cycle // Life Cycle
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_bankroll_details, container, false) _binding = FragmentBankrollDetailsBinding.inflate(inflater, container, false)
return binding.root
// return inflater.inflate(R.layout.fragment_bankroll_details, container, false)
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -81,6 +86,11 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc
super.onCreateOptionsMenu(menu, inflater) super.onCreateOptionsMenu(menu, inflater)
} }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
/** /**
* Init data * Init data
*/ */
@ -104,7 +114,7 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc
val viewManager = LinearLayoutManager(requireContext()) val viewManager = LinearLayoutManager(requireContext())
recyclerView.apply { this.binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
adapter = bankrollAdapter adapter = bankrollAdapter
@ -188,7 +198,7 @@ class BankrollDetailsFragment : RealmFragment(), StaticRowRepresentableDataSourc
// StaticRowRepresentableDataSource // StaticRowRepresentableDataSource
override fun adapterRows(): List<RowRepresentable>? { override fun adapterRows(): List<RowRepresentable> {
return rows return rows
} }

@ -9,13 +9,14 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.github.mikephil.charting.data.LineDataSet import com.github.mikephil.charting.data.LineDataSet
import io.realm.RealmResults import io.realm.RealmResults
import kotlinx.android.synthetic.main.fragment_bankroll.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager
import net.pokeranalytics.android.databinding.FragmentBankrollBinding
import net.pokeranalytics.android.databinding.FragmentBankrollDetailsBinding
import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.interfaces.Deletable import net.pokeranalytics.android.model.interfaces.Deletable
import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.model.realm.Bankroll
@ -62,6 +63,9 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
private lateinit var bankrolls: RealmResults<Bankroll> private lateinit var bankrolls: RealmResults<Bankroll>
private var _binding: FragmentBankrollBinding? = null
private val binding get() = _binding!!
override fun deletableItems(): List<Deletable> { override fun deletableItems(): List<Deletable> {
return this.bankrolls return this.bankrolls
} }
@ -70,7 +74,8 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_bankroll, container, false) _binding = FragmentBankrollBinding.inflate(inflater, container, false)
return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -103,6 +108,11 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
} }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
/** /**
* Init data * Init data
*/ */
@ -153,13 +163,13 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
val viewManager = LinearLayoutManager(requireContext()) val viewManager = LinearLayoutManager(requireContext())
recyclerView.apply { this.binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
adapter = dataListAdapter adapter = dataListAdapter
} }
addButton.setOnClickListener { this.binding.addButton.setOnClickListener {
EditableDataActivity.newInstanceForResult( EditableDataActivity.newInstanceForResult(
this@BankrollFragment, this@BankrollFragment,
dataType = LiveData.BANKROLL, dataType = LiveData.BANKROLL,

@ -13,13 +13,14 @@ import com.github.mikephil.charting.data.BarDataSet
import com.github.mikephil.charting.data.LineDataSet import com.github.mikephil.charting.data.LineDataSet
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import io.realm.Realm import io.realm.Realm
import kotlinx.android.synthetic.main.fragment_calendar_details.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.calcul.defaultStatEntries
import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.Calculator
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.databinding.FragmentCalendarDetailsBinding
import net.pokeranalytics.android.model.filter.Query import net.pokeranalytics.android.model.filter.Query
import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.filter.QueryCondition
import net.pokeranalytics.android.ui.activity.GraphActivity import net.pokeranalytics.android.ui.activity.GraphActivity
@ -53,22 +54,12 @@ class CalendarDetailsFragment : BaseFragment(), StaticRowRepresentableDataSource
private var rowRepresentables: ArrayList<RowRepresentable> = ArrayList() private var rowRepresentables: ArrayList<RowRepresentable> = ArrayList()
/** private var _binding: FragmentCalendarDetailsBinding? = null
* Set data private val binding get() = _binding!!
*/
// fun setData(computedResults: ComputedResults?, sessionTypeCondition: QueryCondition?, title: String?) {
//
// this.computedResults = computedResults
// this.sessionTypeCondition = sessionTypeCondition
// this.title = title
//
// displayData()
// launchStatComputation()
//
// }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_calendar_details, container, false) _binding = FragmentCalendarDetailsBinding.inflate(inflater, container, false)
return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -77,6 +68,11 @@ class CalendarDetailsFragment : BaseFragment(), StaticRowRepresentableDataSource
launchStatComputation() launchStatComputation()
} }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
/** /**
* Init UI * Init UI
*/ */
@ -95,9 +91,9 @@ class CalendarDetailsFragment : BaseFragment(), StaticRowRepresentableDataSource
} }
} }
tabs.getTabAt(tabIndexToSelect)?.select() this.binding.tabs.getTabAt(tabIndexToSelect)?.select()
tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { this.binding.tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) { override fun onTabSelected(tab: TabLayout.Tab) {
when (tab.position) { when (tab.position) {
0 -> model.sessionTypeCondition = null 0 -> model.sessionTypeCondition = null
@ -118,7 +114,7 @@ class CalendarDetailsFragment : BaseFragment(), StaticRowRepresentableDataSource
val viewManager = LinearLayoutManager(requireContext()) val viewManager = LinearLayoutManager(requireContext())
recyclerView.apply { this.binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
adapter = statsAdapter adapter = statsAdapter
@ -129,7 +125,7 @@ class CalendarDetailsFragment : BaseFragment(), StaticRowRepresentableDataSource
// StaticRowRepresentableDataSource // StaticRowRepresentableDataSource
override fun adapterRows(): List<RowRepresentable>? { override fun adapterRows(): List<RowRepresentable> {
return rowRepresentables return rowRepresentables
} }
@ -164,9 +160,9 @@ class CalendarDetailsFragment : BaseFragment(), StaticRowRepresentableDataSource
*/ */
private fun launchStatComputation() { private fun launchStatComputation() {
progressBar.isVisible = true this.binding.progressBar.isVisible = true
progressBar.animate().alpha(1f).start() this.binding.progressBar.animate().alpha(1f).start()
recyclerView.animate().alpha(0f).start() this.binding.recyclerView.animate().alpha(0f).start()
this.model.computedResults?.let { computedResults -> this.model.computedResults?.let { computedResults ->
@ -226,10 +222,10 @@ class CalendarDetailsFragment : BaseFragment(), StaticRowRepresentableDataSource
launch(Dispatchers.Main) { launch(Dispatchers.Main) {
statsAdapter.notifyDataSetChanged() statsAdapter.notifyDataSetChanged()
progressBar.animate().cancel() binding.progressBar.animate().cancel()
progressBar.animate().alpha(0f).withEndAction { progressBar.isVisible = false }.start() binding.progressBar.animate().alpha(0f).withEndAction { binding.progressBar.isVisible = false }.start()
recyclerView.animate().cancel() binding.recyclerView.animate().cancel()
recyclerView.animate().alpha(1f).start() binding.recyclerView.animate().alpha(1f).start()
} }
} }
} }

@ -7,15 +7,14 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import io.realm.Realm import io.realm.Realm
import kotlinx.android.synthetic.main.fragment_calendar.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.Calculator
import net.pokeranalytics.android.calculus.ComputedResults import net.pokeranalytics.android.calculus.ComputedResults
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.databinding.FragmentCalendarBinding
import net.pokeranalytics.android.model.Criteria import net.pokeranalytics.android.model.Criteria
import net.pokeranalytics.android.model.combined import net.pokeranalytics.android.model.combined
import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.filter.QueryCondition
@ -72,11 +71,15 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable
TimeFilter.MONTH TimeFilter.MONTH
private var currentStat = Stat.NET_RESULT private var currentStat = Stat.NET_RESULT
private var _binding: FragmentCalendarBinding? = null
private val binding get() = _binding!!
// Life Cycle // Life Cycle
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_calendar, container, false) _binding = FragmentCalendarBinding.inflate(inflater, container, false)
return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -86,7 +89,14 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable
listenRealmChanges(this, ComputableResult::class.java) listenRealmChanges(this, ComputableResult::class.java)
} }
override fun adapterRows(): List<RowRepresentable>? { override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
//
override fun adapterRows(): List<RowRepresentable> {
return rows return rows
} }
@ -134,12 +144,12 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable
private fun initUI() { private fun initUI() {
CalendarTabs.values().forEach { CalendarTabs.values().forEach {
val tab = tabs.newTab() val tab = binding.tabs.newTab()
tab.text = getString(it.resId) tab.text = getString(it.resId)
tabs.addTab(tab) binding.tabs.addTab(tab)
} }
tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { binding.tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) { override fun onTabSelected(tab: TabLayout.Tab) {
when (tab.position) { when (tab.position) {
0 -> currentStat = Stat.NET_RESULT 0 -> currentStat = Stat.NET_RESULT
@ -162,57 +172,57 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable
}) })
// Manage session type queryWith // Manage session type queryWith
filterSessionAll.setOnCheckedChangeListener { _, isChecked -> binding.filterSessionAll.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) { if (isChecked) {
sessionTypeCondition = null sessionTypeCondition = null
filterSessionCash.isChecked = false binding.filterSessionCash.isChecked = false
filterSessionTournament.isChecked = false binding.filterSessionTournament.isChecked = false
launchAsyncStatComputation() launchAsyncStatComputation()
} else if (sessionTypeCondition == null) { } else if (sessionTypeCondition == null) {
filterSessionAll.isChecked = true binding.filterSessionAll.isChecked = true
} }
} }
filterSessionCash.setOnCheckedChangeListener { _, isChecked -> binding.filterSessionCash.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) { if (isChecked) {
sessionTypeCondition = QueryCondition.IsCash sessionTypeCondition = QueryCondition.IsCash
filterSessionAll.isChecked = false binding.filterSessionAll.isChecked = false
filterSessionTournament.isChecked = false binding.filterSessionTournament.isChecked = false
launchAsyncStatComputation() launchAsyncStatComputation()
} else if (sessionTypeCondition == QueryCondition.IsCash) { } else if (sessionTypeCondition == QueryCondition.IsCash) {
filterSessionCash.isChecked = true binding.filterSessionCash.isChecked = true
} }
} }
filterSessionTournament.setOnCheckedChangeListener { _, isChecked -> binding.filterSessionTournament.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) { if (isChecked) {
sessionTypeCondition = QueryCondition.IsTournament sessionTypeCondition = QueryCondition.IsTournament
filterSessionAll.isChecked = false binding.filterSessionAll.isChecked = false
filterSessionCash.isChecked = false binding.filterSessionCash.isChecked = false
launchAsyncStatComputation() launchAsyncStatComputation()
} else if (sessionTypeCondition == QueryCondition.IsTournament) { } else if (sessionTypeCondition == QueryCondition.IsTournament) {
filterSessionTournament.isChecked = true binding.filterSessionTournament.isChecked = true
} }
} }
// Manage time queryWith // Manage time queryWith
filterTimeMonth.setOnCheckedChangeListener { _, isChecked -> binding.filterTimeMonth.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) { if (isChecked) {
currentTimeFilter = currentTimeFilter =
TimeFilter.MONTH TimeFilter.MONTH
filterTimeYear.isChecked = false binding.filterTimeYear.isChecked = false
displayData() displayData()
} else if (currentTimeFilter == TimeFilter.MONTH) { } else if (currentTimeFilter == TimeFilter.MONTH) {
filterTimeMonth.isChecked = true binding.filterTimeMonth.isChecked = true
} }
} }
filterTimeYear.setOnCheckedChangeListener { _, isChecked -> binding.filterTimeYear.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) { if (isChecked) {
currentTimeFilter = currentTimeFilter =
TimeFilter.YEAR TimeFilter.YEAR
filterTimeMonth.isChecked = false binding.filterTimeMonth.isChecked = false
displayData() displayData()
} else if (currentTimeFilter == TimeFilter.YEAR) { } else if (currentTimeFilter == TimeFilter.YEAR) {
filterTimeYear.isChecked = true binding.filterTimeYear.isChecked = true
} }
} }
@ -220,7 +230,7 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable
calendarAdapter = RowRepresentableAdapter(this, this) calendarAdapter = RowRepresentableAdapter(this, this)
recyclerView.apply { binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
adapter = calendarAdapter adapter = calendarAdapter
@ -232,8 +242,8 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable
*/ */
private fun launchAsyncStatComputation() { private fun launchAsyncStatComputation() {
progressBar?.showWithAnimation() binding.progressBar?.showWithAnimation()
recyclerView?.hideWithAnimation() binding.recyclerView?.hideWithAnimation()
GlobalScope.launch { GlobalScope.launch {
@ -411,8 +421,8 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable
calendarAdapter.notifyDataSetChanged() calendarAdapter.notifyDataSetChanged()
progressBar?.hideWithAnimation() binding.progressBar.hideWithAnimation()
recyclerView?.showWithAnimation() binding.recyclerView.showWithAnimation()
} }

@ -9,17 +9,15 @@ import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.chip.ChipGroup import com.google.android.material.chip.ChipGroup
import kotlinx.android.synthetic.main.fragment_custom_view.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentCustomViewBinding
import net.pokeranalytics.android.model.realm.CustomField import net.pokeranalytics.android.model.realm.CustomField
import net.pokeranalytics.android.model.realm.CustomFieldEntry import net.pokeranalytics.android.model.realm.CustomFieldEntry
import net.pokeranalytics.android.ui.activity.components.BaseActivity
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.extensions.ChipGroupExtension import net.pokeranalytics.android.ui.extensions.ChipGroupExtension
import net.pokeranalytics.android.ui.extensions.px import net.pokeranalytics.android.ui.extensions.px
import net.pokeranalytics.android.ui.extensions.showAlertDialog import net.pokeranalytics.android.ui.extensions.showAlertDialog
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.RowRepresentableEditDescriptor import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomFieldRow import net.pokeranalytics.android.ui.view.rowrepresentable.CustomFieldRow
@ -102,18 +100,25 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
} }
}) })
private var _binding: FragmentCustomViewBinding? = null
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_custom_view, container, false) _binding = FragmentCustomViewBinding.inflate(inflater, container, false)
return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initUI() initUI()
} }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun getDataSource(): RowRepresentableDataSource { override fun getDataSource(): RowRepresentableDataSource {
return this return this
} }
@ -205,29 +210,34 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
* Init UI * Init UI
*/ */
private fun initUI() { private fun initUI() {
val addItem = binding.addItem
val sortChoices = binding.sortChoices
val sortDescending = binding.sortDescending
val recyclerView = binding.recyclerView
customField.updateRowRepresentation() customField.updateRowRepresentation()
bottomBar.translationY = 72f.px binding.bottomBar.translationY = 72f.px
bottomBar.visibility = View.VISIBLE binding.bottomBar.visibility = View.VISIBLE
if (customField.sortCondition == CustomField.Sort.DEFAULT.uniqueIdentifier) { if (customField.sortCondition == CustomField.Sort.DEFAULT.uniqueIdentifier) {
itemTouchHelper.attachToRecyclerView(recyclerView) itemTouchHelper.attachToRecyclerView(binding.recyclerView)
} else { } else {
itemTouchHelper.attachToRecyclerView(null) itemTouchHelper.attachToRecyclerView(null)
} }
when (customField.sortCondition) { when (customField.sortCondition) {
CustomField.Sort.DEFAULT.uniqueIdentifier -> sortDefault.isChecked = true CustomField.Sort.DEFAULT.uniqueIdentifier -> binding.sortDefault.isChecked = true
CustomField.Sort.ASCENDING.uniqueIdentifier -> sortAscending.isChecked = true CustomField.Sort.ASCENDING.uniqueIdentifier -> binding.sortAscending.isChecked = true
CustomField.Sort.DESCENDING.uniqueIdentifier -> sortDescending.isChecked = true CustomField.Sort.DESCENDING.uniqueIdentifier -> binding.sortDescending.isChecked = true
} }
addItem.setOnClickListener { binding.addItem.setOnClickListener {
val customFieldEntry = customField.addEntry() val customFieldEntry = customField.addEntry()
rowRepresentableAdapter.notifyDataSetChanged() rowRepresentableAdapter.notifyDataSetChanged()
onRowSelected(-1, customFieldEntry) onRowSelected(-1, customFieldEntry)
} }
sortChoices.setOnCheckedChangeListener(object : ChipGroupExtension.SingleSelectionOnCheckedListener() { binding.sortChoices.setOnCheckedChangeListener(object : ChipGroupExtension.SingleSelectionOnCheckedListener() {
override fun onCheckedChanged(group: ChipGroup, checkedId: Int) { override fun onCheckedChanged(group: ChipGroup, checkedId: Int) {
super.onCheckedChanged(group, checkedId) super.onCheckedChanged(group, checkedId)
@ -243,7 +253,7 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
} }
if (customField.sortCondition == CustomField.Sort.DEFAULT.uniqueIdentifier) { if (customField.sortCondition == CustomField.Sort.DEFAULT.uniqueIdentifier) {
itemTouchHelper.attachToRecyclerView(recyclerView) itemTouchHelper.attachToRecyclerView(binding.recyclerView)
} else { } else {
itemTouchHelper.attachToRecyclerView(null) itemTouchHelper.attachToRecyclerView(null)
} }
@ -266,6 +276,7 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
* Update UI * Update UI
*/ */
private fun updateUI() { private fun updateUI() {
val bottomBar = binding.bottomBar
if (customField.type == CustomField.Type.LIST.uniqueIdentifier) { if (customField.type == CustomField.Type.LIST.uniqueIdentifier) {
bottomBar.animate().translationY(0f.px) bottomBar.animate().translationY(0f.px)
.setInterpolator(FastOutSlowInInterpolator()) .setInterpolator(FastOutSlowInInterpolator())

@ -4,11 +4,12 @@ import android.os.Bundle
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.Toolbar
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import io.realm.RealmModel 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.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.interfaces.Editable import net.pokeranalytics.android.model.interfaces.Editable
import net.pokeranalytics.android.model.interfaces.NameManageable import net.pokeranalytics.android.model.interfaces.NameManageable
import net.pokeranalytics.android.model.utils.CrashLogging import net.pokeranalytics.android.model.utils.CrashLogging
@ -87,6 +88,8 @@ open class EditableDataFragment : DataManagerFragment(), RowRepresentableDelegat
val liveDataType = this.model.liveDataType val liveDataType = this.model.liveDataType
val toolbar = this.view?.findViewById<Toolbar>(R.id.toolbar)
val data: RealmModel? = liveDataType.getData(this.getRealm(), this.model.primaryKey) val data: RealmModel? = liveDataType.getData(this.getRealm(), this.model.primaryKey)
data?.let { data?.let {
@ -96,13 +99,16 @@ open class EditableDataFragment : DataManagerFragment(), RowRepresentableDelegat
liveDataType.updateEntityLocalizedTitle(requireContext()) liveDataType.updateEntityLocalizedTitle(requireContext())
} }
this.appBar.toolbar.title = title toolbar?.title = title
deleteButtonShouldAppear = true deleteButtonShouldAppear = true
isUpdating = true isUpdating = true
} ?: run { } ?: run {
this.appBar.toolbar.title = liveDataType.newEntityLocalizedTitle(requireContext()) toolbar?.title = liveDataType.newEntityLocalizedTitle(requireContext())
} }
val recyclerView = this.view?.findViewById<RecyclerView>(R.id.recyclerView) ?: throw
PAIllegalStateException("recyclerView not found")
val viewManager = LinearLayoutManager(requireContext()) val viewManager = LinearLayoutManager(requireContext())
recyclerView.apply { recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
@ -112,7 +118,7 @@ open class EditableDataFragment : DataManagerFragment(), RowRepresentableDelegat
val dataSource = getDataSource() val dataSource = getDataSource()
this.rowRepresentableAdapter = RowRepresentableAdapter(getDataSource(), this) this.rowRepresentableAdapter = RowRepresentableAdapter(getDataSource(), this)
//this.rowRepresentableAdapter.setHasStableIds(true) //this.rowRepresentableAdapter.setHasStableIds(true)
this.recyclerView.adapter = rowRepresentableAdapter recyclerView.adapter = rowRepresentableAdapter
// When creating an object, open automatically the keyboard for the first row // When creating an object, open automatically the keyboard for the first row
if (!deleteButtonShouldAppear && shouldOpenKeyboard) { if (!deleteButtonShouldAppear && shouldOpenKeyboard) {

@ -9,12 +9,12 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import kotlinx.android.synthetic.main.fragment_player.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentPlayerBinding
import net.pokeranalytics.android.model.realm.Comment import net.pokeranalytics.android.model.realm.Comment
import net.pokeranalytics.android.model.realm.Player import net.pokeranalytics.android.model.realm.Player
import net.pokeranalytics.android.ui.activity.ColorPickerActivity import net.pokeranalytics.android.ui.activity.ColorPickerActivity
@ -22,7 +22,6 @@ import net.pokeranalytics.android.ui.activity.components.MediaActivity
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.extensions.showAlertDialog import net.pokeranalytics.android.ui.extensions.showAlertDialog
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.RowRepresentableEditDescriptor import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.RowViewType
@ -46,11 +45,14 @@ class PlayerDataFragment : EditableDataFragment(), StaticRowRepresentableDataSou
private var mediaActivity: MediaActivity? = null private var mediaActivity: MediaActivity? = null
private var _binding: FragmentPlayerBinding? = null
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
shouldOpenKeyboard = false shouldOpenKeyboard = false
return inflater.inflate(R.layout.fragment_player, container, false) _binding = FragmentPlayerBinding.inflate(inflater, container, false)
return binding.root
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
@ -68,6 +70,11 @@ class PlayerDataFragment : EditableDataFragment(), StaticRowRepresentableDataSou
initUI() initUI()
} }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
/** /**
* Init UI * Init UI
*/ */
@ -80,7 +87,7 @@ class PlayerDataFragment : EditableDataFragment(), StaticRowRepresentableDataSou
onRowSelected(0, PlayerRow.NAME) onRowSelected(0, PlayerRow.NAME)
} }
addComment.setOnClickListener { binding.addComment.setOnClickListener {
val comment = player.addComment() val comment = player.addComment()
rowRepresentableAdapter.notifyDataSetChanged() rowRepresentableAdapter.notifyDataSetChanged()
onRowSelected(-1, comment) onRowSelected(-1, comment)

@ -11,8 +11,8 @@ import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
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 net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentDataListBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.interfaces.Deletable import net.pokeranalytics.android.model.interfaces.Deletable
@ -44,6 +44,9 @@ open class DataListFragment : DeletableItemFragment(), RowRepresentableDelegate
private var menu: Menu? = null private var menu: Menu? = null
private var searchView: SearchView? = null private var searchView: SearchView? = null
private var _binding: FragmentDataListBinding? = null
private val binding get() = _binding!!
open fun retrieveItems(realm: Realm): RealmResults<out Deletable> { open fun retrieveItems(realm: Realm): RealmResults<out Deletable> {
return realm.sorted(this.model.identifiableClass, return realm.sorted(this.model.identifiableClass,
editableOnly = true, editableOnly = true,
@ -56,7 +59,8 @@ open class DataListFragment : DeletableItemFragment(), RowRepresentableDelegate
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_data_list, container, false) _binding = FragmentDataListBinding.inflate(inflater, container, false)
return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -65,6 +69,11 @@ open class DataListFragment : DeletableItemFragment(), RowRepresentableDelegate
initUI() initUI()
} }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
fun initData() { fun initData() {
val itemIds = this.model.itemIds val itemIds = this.model.itemIds
@ -106,14 +115,14 @@ open class DataListFragment : DeletableItemFragment(), RowRepresentableDelegate
val itemTouchHelper = ItemTouchHelper(swipeToDelete) val itemTouchHelper = ItemTouchHelper(swipeToDelete)
recyclerView.apply { binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
adapter = dataListAdapter adapter = dataListAdapter
itemTouchHelper.attachToRecyclerView(this) itemTouchHelper.attachToRecyclerView(this)
} }
this.addButton.setOnClickListener { binding.addButton.setOnClickListener {
EditableDataActivity.newInstanceForResult(this, EditableDataActivity.newInstanceForResult(this,
dataType = this.model.dataType, dataType = this.model.dataType,
@ -123,13 +132,13 @@ open class DataListFragment : DeletableItemFragment(), RowRepresentableDelegate
} }
this.addButton.isVisible = this.model.showAddButton binding.addButton.isVisible = this.model.showAddButton
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
this.recyclerView?.adapter?.notifyDataSetChanged() binding.recyclerView.adapter?.notifyDataSetChanged()
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {

@ -10,13 +10,12 @@ import androidx.core.view.isVisible
import androidx.interpolator.view.animation.FastOutSlowInInterpolator import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import com.android.billingclient.api.Purchase import com.android.billingclient.api.Purchase
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import com.google.firebase.crashlytics.FirebaseCrashlytics
import io.realm.RealmModel import io.realm.RealmModel
import io.realm.RealmResults import io.realm.RealmResults
import io.realm.Sort import io.realm.Sort
import io.realm.kotlin.where import io.realm.kotlin.where
import kotlinx.android.synthetic.main.fragment_feed.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentFeedBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.interfaces.Editable import net.pokeranalytics.android.model.interfaces.Editable
@ -105,6 +104,9 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
} }
private var _binding: FragmentFeedBinding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
AppGuard.registerListener(this) AppGuard.registerListener(this)
@ -114,9 +116,10 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_feed, container, false) _binding = FragmentFeedBinding.inflate(inflater, container, false)
return binding.root
} }
override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) { override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) {
@ -219,6 +222,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
realmTransactions.removeAllChangeListeners() realmTransactions.removeAllChangeListeners()
_binding = null
} }
override fun onRowSelected(position: Int, row: RowRepresentable, tag: Int) { override fun onRowSelected(position: Int, row: RowRepresentable, tag: Int) {
@ -250,43 +254,43 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
this.sessionAdapter = FeedSessionRowRepresentableAdapter(getRealm(), this) this.sessionAdapter = FeedSessionRowRepresentableAdapter(getRealm(), this)
registerForContextMenu(this.menuRecyclerView) registerForContextMenu(binding.menuRecyclerView)
val messageToShow: Preferences.FeedMessage? = val messageToShow: Preferences.FeedMessage? =
Preferences.feedMessageToShow(requireContext()) Preferences.feedMessageToShow(requireContext())
if (messageToShow != null) { if (messageToShow != null) {
messageBox.isVisible = true binding.messageBox.isVisible = true
message.text = getString(messageToShow.resId) binding.message.text = getString(messageToShow.resId)
messageToShow.actionResId?.let { messageToShow.actionResId?.let {
messageBoxAction.text = requireContext().getString(it) binding.messageBoxAction.text = requireContext().getString(it)
messageToShow.action(requireContext())?.let { action -> messageToShow.action(requireContext())?.let { action ->
messageBoxAction.setOnClickListener { view -> binding.messageBoxAction.setOnClickListener { view ->
action.invoke(view) action.invoke(view)
hideMessageBox(messageToShow) hideMessageBox(messageToShow)
} }
} }
} ?: run { } ?: run {
messageBoxAction.visibility = View.GONE binding.messageBoxAction.visibility = View.GONE
} }
messageBoxDismiss.text = requireContext().getString(messageToShow.dismissResId) binding.messageBoxDismiss.text = requireContext().getString(messageToShow.dismissResId)
messageBoxDismiss.setOnClickListener { binding.messageBoxDismiss.setOnClickListener {
hideMessageBox(messageToShow) hideMessageBox(messageToShow)
} }
} else { } else {
messageBox.isVisible = false binding.messageBox.isVisible = false
} }
val viewManager = SmoothScrollLinearLayoutManager(requireContext()) val viewManager = SmoothScrollLinearLayoutManager(requireContext())
menuRecyclerView.apply { binding.menuRecyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
} }
// Add button // Add button
addButton.setOnClickListener { binding.addButton.setOnClickListener {
activity?.let { activity?.let {
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(it) val options = ActivityOptionsCompat.makeSceneTransitionAnimation(it)
val intent = Intent(requireContext(), NewDataMenuActivity::class.java) val intent = Intent(requireContext(), NewDataMenuActivity::class.java)
@ -295,7 +299,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
} }
// Tabs // Tabs
tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { binding.tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) { override fun onTabSelected(tab: TabLayout.Tab) {
when (tab.position) { when (tab.position) {
Tab.SESSIONS.ordinal -> { Tab.SESSIONS.ordinal -> {
@ -318,7 +322,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
} }
}) })
this.subscribe.setOnClickListener { binding.subscribe.setOnClickListener {
if (!AppGuard.isProUser) { if (!AppGuard.isProUser) {
BillingActivity.newInstanceForResult(this, false) BillingActivity.newInstanceForResult(this, false)
} else { } else {
@ -330,15 +334,16 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
} }
private fun showSubscriptionButton() { private fun showSubscriptionButton() {
this.subscribe.isVisible = !AppGuard.isProUser this.binding.subscribe.isVisible = !AppGuard.isProUser
} }
private fun hideMessageBox(message: Preferences.FeedMessage) { private fun hideMessageBox(message: Preferences.FeedMessage) {
Preferences.setStopShowingMessage(message, requireContext()) Preferences.setStopShowingMessage(message, requireContext())
val messageBox = binding.messageBox
messageBox.animate().translationY(messageBox.height.toFloat()) messageBox.animate().translationY(messageBox.height.toFloat())
.setInterpolator(FastOutSlowInInterpolator()) .setInterpolator(FastOutSlowInInterpolator())
.withEndAction { messageBox?.isVisible = false } .withEndAction { messageBox.isVisible = false }
.start() .start()
} }
@ -553,7 +558,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
private fun selectTab(tab: Tab) { private fun selectTab(tab: Tab) {
this.currentTab = tab this.currentTab = tab
this.tabs.getTabAt(tab.ordinal)?.select() this.binding.tabs.getTabAt(tab.ordinal)?.select()
setAdapter() setAdapter()
} }
@ -564,9 +569,9 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
private fun setAdapter() { private fun setAdapter() {
when (this.currentTab) { when (this.currentTab) {
Tab.SESSIONS -> menuRecyclerView.adapter = sessionAdapter Tab.SESSIONS -> binding.menuRecyclerView.adapter = sessionAdapter
Tab.TRANSACTIONS -> menuRecyclerView.adapter = transactionAdapter Tab.TRANSACTIONS -> binding.menuRecyclerView.adapter = transactionAdapter
Tab.HAND_HISTORY -> menuRecyclerView.adapter = handHistoryAdapter Tab.HAND_HISTORY -> binding.menuRecyclerView.adapter = handHistoryAdapter
} }
} }

@ -11,13 +11,14 @@ import io.realm.RealmQuery
import io.realm.RealmResults import io.realm.RealmResults
import io.realm.Sort import io.realm.Sort
import io.realm.kotlin.where import io.realm.kotlin.where
import kotlinx.android.synthetic.main.row_feed_session.view.* import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.realm.Filter import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.adapter.BindableHolder import net.pokeranalytics.android.ui.adapter.BindableHolder
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.SessionRowView
import net.pokeranalytics.android.util.extensions.getMonthAndYear import net.pokeranalytics.android.util.extensions.getMonthAndYear
import timber.log.Timber import timber.log.Timber
import java.util.* import java.util.*
@ -74,16 +75,17 @@ class FeedSessionRowRepresentableAdapter(
*/ */
inner class RowSessionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), inner class RowSessionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder { BindableHolder {
private var sessionRow: SessionRowView = itemView.findViewById(R.id.sessionRow)
fun bind(position: Int, row: Session?, adapter: FeedSessionRowRepresentableAdapter) { fun bind(position: Int, row: Session?, adapter: FeedSessionRowRepresentableAdapter) {
itemView.sessionRow.setData(row as Session) this.sessionRow.setData(row as Session)
val listener = View.OnClickListener { val listener = View.OnClickListener {
adapter.delegate?.onRowSelected(position, row) adapter.delegate?.onRowSelected(position, row)
} }
itemView.sessionRow.setOnClickListener(listener) this.sessionRow.setOnClickListener(listener)
itemView.sessionRow.setOnLongClickListener { this.sessionRow.setOnLongClickListener {
adapter.delegate?.onRowLongClick(itemView, row, adapterPosition) adapter.delegate?.onRowLongClick(itemView, row, adapterPosition)
return@setOnLongClickListener true return@setOnLongClickListener true
} }

@ -6,12 +6,12 @@ import android.view.ViewGroup
import androidx.appcompat.widget.AppCompatTextView import androidx.appcompat.widget.AppCompatTextView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import io.realm.RealmResults import io.realm.RealmResults
import kotlinx.android.synthetic.main.row_transaction.view.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.Transaction import net.pokeranalytics.android.model.realm.Transaction
import net.pokeranalytics.android.ui.adapter.BindableHolder import net.pokeranalytics.android.ui.adapter.BindableHolder
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.TransactionRowView
import net.pokeranalytics.android.util.NULL_TEXT import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.extensions.getMonthAndYear import net.pokeranalytics.android.util.extensions.getMonthAndYear
import java.util.* import java.util.*
@ -42,14 +42,15 @@ class FeedTransactionRowRepresentableAdapter(
*/ */
inner class RowTransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), inner class RowTransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder { BindableHolder {
private var transactionRow: TransactionRowView = itemView.findViewById(R.id.transactionRow)
fun bind(position: Int, row: Transaction?, adapter: FeedTransactionRowRepresentableAdapter) { fun bind(position: Int, row: Transaction?, adapter: FeedTransactionRowRepresentableAdapter) {
itemView.transactionRow.setData(row as Transaction) this.transactionRow.setData(row as Transaction)
val listener = View.OnClickListener { val listener = View.OnClickListener {
adapter.delegate?.onRowSelected(position, row) adapter.delegate?.onRowSelected(position, row)
} }
itemView.transactionRow.setOnClickListener(listener) this.transactionRow.setOnClickListener(listener)
} }
} }

@ -9,14 +9,14 @@ import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.ViewAnimationUtils import android.view.ViewAnimationUtils
import kotlinx.android.synthetic.main.activity_new_data.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import net.pokeranalytics.android.R import net.pokeranalytics.android.databinding.ActivityNewDataBinding
import net.pokeranalytics.android.ui.activity.components.BaseActivity import net.pokeranalytics.android.ui.activity.components.BaseActivity
import net.pokeranalytics.android.ui.extensions.px import net.pokeranalytics.android.ui.extensions.px
import kotlin.math.max
class NewDataMenuActivity : BaseActivity() { class NewDataMenuActivity : BaseActivity() {
@ -36,6 +36,8 @@ class NewDataMenuActivity : BaseActivity() {
private var menuWillBeHidden = false private var menuWillBeHidden = false
private val fabSize = 48.px private val fabSize = 48.px
private lateinit var binding: ActivityNewDataBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -43,7 +45,9 @@ class NewDataMenuActivity : BaseActivity() {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
} }
setContentView(R.layout.activity_new_data) binding = ActivityNewDataBinding.inflate(layoutInflater)
setContentView(binding.root)
initUI() initUI()
} }
@ -63,27 +67,27 @@ class NewDataMenuActivity : BaseActivity() {
overridePendingTransition(0, 0) overridePendingTransition(0, 0)
container.viewTreeObserver.addOnGlobalLayoutListener { binding.container.viewTreeObserver.addOnGlobalLayoutListener {
showMenu() showMenu()
} }
newCashGame.setOnClickListener { binding.newCashGame.setOnClickListener {
finishWithResult(0) finishWithResult(0)
} }
newTournament.setOnClickListener { binding.newTournament.setOnClickListener {
finishWithResult(1) finishWithResult(1)
} }
newTransaction.setOnClickListener { binding.newTransaction.setOnClickListener {
finishWithResult(2) finishWithResult(2)
} }
new_hand_history.setOnClickListener { binding.newHandHistory.setOnClickListener {
finishWithResult(3) finishWithResult(3)
} }
container.setOnClickListener { binding.container.setOnClickListener {
hideMenu() hideMenu()
} }
} }
@ -112,9 +116,10 @@ class NewDataMenuActivity : BaseActivity() {
*/ */
private fun showMenu() { private fun showMenu() {
val menuContainer = binding.menuContainer
val cx = menuContainer.measuredWidth - fabSize / 2 val cx = menuContainer.measuredWidth - fabSize / 2
val cy = menuContainer.measuredHeight - fabSize / 2 val cy = menuContainer.measuredHeight - fabSize / 2
val finalRadius = Math.max(menuContainer.width, menuContainer.height) val finalRadius = max(menuContainer.width, menuContainer.height)
val anim = ViewAnimationUtils.createCircularReveal(menuContainer, cx, cy, 0f, finalRadius.toFloat()) val anim = ViewAnimationUtils.createCircularReveal(menuContainer, cx, cy, 0f, finalRadius.toFloat())
anim.duration = 150 anim.duration = 150
@ -132,6 +137,7 @@ class NewDataMenuActivity : BaseActivity() {
} }
menuWillBeHidden = true menuWillBeHidden = true
val menuContainer = binding.menuContainer
val cx = menuContainer.measuredWidth - fabSize / 2 val cx = menuContainer.measuredWidth - fabSize / 2
val cy = menuContainer.measuredHeight - fabSize / 2 val cy = menuContainer.measuredHeight - fabSize / 2
val initialRadius = menuContainer.width val initialRadius = menuContainer.width

@ -6,9 +6,8 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.fragment_filter_details.*
import kotlinx.android.synthetic.main.fragment_filter_details.view.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentFilterDetailsBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.filter.QueryCondition
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
@ -30,6 +29,9 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate {
private lateinit var rowRepresentableAdapter: RowRepresentableAdapter private lateinit var rowRepresentableAdapter: RowRepresentableAdapter
private var _binding: FragmentFilterDetailsBinding? = null
private val binding get() = _binding!!
companion object { companion object {
fun newInstance(categoryRow: FilterCategoryRow): FilterDetailsFragment { fun newInstance(categoryRow: FilterCategoryRow): FilterDetailsFragment {
@ -44,7 +46,8 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_filter_details, container, false) _binding = FragmentFilterDetailsBinding.inflate(inflater, container, false)
return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -58,6 +61,11 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate {
saveData() saveData()
} }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
/** /**
* Init UI * Init UI
*/ */
@ -65,11 +73,11 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate {
setDisplayHomeAsUpEnabled(true) setDisplayHomeAsUpEnabled(true)
this.appBar.toolbar.title = getString(R.string.filter) this.binding.toolbar.title = getString(R.string.filter)
val viewManager = LinearLayoutManager(requireContext()) val viewManager = LinearLayoutManager(requireContext())
recyclerView.apply { binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
} }
@ -95,10 +103,10 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate {
Timber.d(">> Filter = ${this.activityModel.currentFilter}") Timber.d(">> Filter = ${this.activityModel.currentFilter}")
Timber.d("selectedRow = ${this.activityModel.selectedCategoryRow}") Timber.d("selectedRow = ${this.activityModel.selectedCategoryRow}")
this.appBar.toolbar.title = this.activityModel.selectedCategoryRow?.localizedTitle(requireContext()) this.binding.toolbar.title = this.activityModel.selectedCategoryRow?.localizedTitle(requireContext())
this.rowRepresentableAdapter = RowRepresentableAdapter(this.model, this) this.rowRepresentableAdapter = RowRepresentableAdapter(this.model, this)
this.recyclerView.adapter = rowRepresentableAdapter this.binding.recyclerView.adapter = rowRepresentableAdapter
} }
override fun onRowSelected(position: Int, row: RowRepresentable, tag: Int) { override fun onRowSelected(position: Int, row: RowRepresentable, tag: Int) {

@ -8,11 +8,8 @@ import androidx.core.view.isVisible
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import kotlinx.android.synthetic.main.fragment_editable_data.appBar
import kotlinx.android.synthetic.main.fragment_editable_data.recyclerView
import kotlinx.android.synthetic.main.fragment_filters.*
import kotlinx.android.synthetic.main.fragment_filters.view.toolbar
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentFiltersBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.realm.Filter import net.pokeranalytics.android.model.realm.Filter
@ -44,9 +41,13 @@ open class FiltersFragment : RealmFragment(), RowRepresentableDelegate {
private var showMostUsedFiltersLayout = true private var showMostUsedFiltersLayout = true
private var _binding: FragmentFiltersBinding? = null
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_filters, container, false) _binding = FragmentFiltersBinding.inflate(inflater, container, false)
return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -102,6 +103,11 @@ open class FiltersFragment : RealmFragment(), RowRepresentableDelegate {
return true return true
} }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
/** /**
* Init UI * Init UI
*/ */
@ -109,20 +115,20 @@ open class FiltersFragment : RealmFragment(), RowRepresentableDelegate {
setDisplayHomeAsUpEnabled(true) setDisplayHomeAsUpEnabled(true)
this.appBar.toolbar.title = getString(R.string.filter) this.binding.toolbar.title = getString(R.string.filter)
val viewManager = LinearLayoutManager(requireContext()) val viewManager = LinearLayoutManager(requireContext())
recyclerView.apply { this.binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
} }
moreFilters.setOnClickListener { this.binding.moreFilters.setOnClickListener {
LiveData.FILTER.subType = this.model.filterableType?.uniqueIdentifier LiveData.FILTER.subType = this.model.filterableType?.uniqueIdentifier
FiltersListActivity.newSelectInstance(this, false) FiltersListActivity.newSelectInstance(this, false)
} }
mostUsedFiltersLayout.isVisible = showMostUsedFiltersLayout this.binding.mostUsedFiltersLayout.isVisible = showMostUsedFiltersLayout
} }
/** /**
@ -133,7 +139,7 @@ open class FiltersFragment : RealmFragment(), RowRepresentableDelegate {
this.model.init(getRealm()) this.model.init(getRealm())
this.rowRepresentableAdapter = RowRepresentableAdapter(this.model, this) this.rowRepresentableAdapter = RowRepresentableAdapter(this.model, this)
this.recyclerView.adapter = rowRepresentableAdapter this.binding.recyclerView.adapter = rowRepresentableAdapter
} }
@ -157,11 +163,11 @@ open class FiltersFragment : RealmFragment(), RowRepresentableDelegate {
val currentFilterId = Preferences.getActiveFilterId(requireContext()) val currentFilterId = Preferences.getActiveFilterId(requireContext())
if (this.model.isUpdating || filters.isEmpty() || (filters.size == 1 && filters.first()?.id == currentFilterId)) { if (this.model.isUpdating || filters.isEmpty() || (filters.size == 1 && filters.first()?.id == currentFilterId)) {
mostUsedFiltersLayout.visibility = View.GONE this.binding.mostUsedFiltersLayout.visibility = View.GONE
return return
} }
mostUsedFilters.removeAllViews() this.binding.mostUsedFilters.removeAllViews()
filters.forEach { filter -> filters.forEach { filter ->
if (nbChips < MOST_USED_FILTERS_DISPLAYED) { if (nbChips < MOST_USED_FILTERS_DISPLAYED) {
@ -185,7 +191,7 @@ open class FiltersFragment : RealmFragment(), RowRepresentableDelegate {
finishActivityWithResult("") finishActivityWithResult("")
} }
} }
mostUsedFilters.addView(chip) this.binding.mostUsedFilters.addView(chip)
nbChips++ nbChips++
} }
} }
@ -249,7 +255,7 @@ open class FiltersFragment : RealmFragment(), RowRepresentableDelegate {
fun updateMostUsedFiltersVisibility(visible: Boolean) { fun updateMostUsedFiltersVisibility(visible: Boolean) {
Timber.d("updateMostUsedFiltersVisibility: $visible") Timber.d("updateMostUsedFiltersVisibility: $visible")
showMostUsedFiltersLayout = visible showMostUsedFiltersLayout = visible
mostUsedFiltersLayout?.isVisible = visible this.binding.mostUsedFiltersLayout.isVisible = visible
} }
} }

@ -4,9 +4,8 @@ import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import net.pokeranalytics.android.model.realm.Filter import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment
import net.pokeranalytics.android.ui.modules.filter.FilterHandler.Companion.INTENT_FILTER_UPDATE_FILTER_UI
import net.pokeranalytics.android.ui.modules.datalist.DataListFragment import net.pokeranalytics.android.ui.modules.datalist.DataListFragment
import net.pokeranalytics.android.ui.modules.filter.FilterHandler.Companion.INTENT_FILTER_UPDATE_FILTER_UI
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.util.Preferences import net.pokeranalytics.android.util.Preferences

@ -3,24 +3,13 @@ package net.pokeranalytics.android.ui.modules.handhistory.editor
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.text.InputType import android.text.InputType
import android.view.* import android.view.*
import android.widget.Button import android.widget.*
import android.widget.EditText import androidx.appcompat.widget.AppCompatButton
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.view.isEmpty import androidx.core.view.isEmpty
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import kotlinx.android.synthetic.main.row_hand_action.view.* import com.google.android.material.internal.FlowLayout
import kotlinx.android.synthetic.main.row_hand_action_read.view.*
import kotlinx.android.synthetic.main.row_hand_cards.view.*
import kotlinx.android.synthetic.main.row_hand_player_summary.view.*
import kotlinx.android.synthetic.main.row_hhsettings_player_setup.view.*
import kotlinx.android.synthetic.main.row_hhsettings_player_setup.view.position_button
import kotlinx.android.synthetic.main.row_hhsettings_player_setup.view.ps_hand_layout
import kotlinx.android.synthetic.main.row_hhsettings_player_setup_read.view.*
import kotlinx.android.synthetic.main.row_hhsettings_straddle.view.*
import kotlinx.android.synthetic.main.row_recycler.view.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.handhistory.Position import net.pokeranalytics.android.model.handhistory.Position
@ -69,9 +58,9 @@ enum class HandRowType(var layoutRes: Int) : ViewIdentifier, RowRepresentable {
override val bottomSheetType: BottomSheetType override val bottomSheetType: BottomSheetType
get() { get() {
return when(this) { return when(this) {
PLAYER_NUMBER -> BottomSheetType.GRID PLAYER_NUMBER -> BottomSheetType.GRID
COMMENT -> BottomSheetType.EDIT_TEXT_MULTI_LINES COMMENT -> BottomSheetType.EDIT_TEXT_MULTI_LINES
ANTE -> BottomSheetType.NUMERIC_TEXT ANTE -> BottomSheetType.NUMERIC_TEXT
else -> BottomSheetType.NONE else -> BottomSheetType.NONE
} }
} }
@ -79,11 +68,11 @@ enum class HandRowType(var layoutRes: Int) : ViewIdentifier, RowRepresentable {
override val resId: Int? override val resId: Int?
get() { get() {
return when(this) { return when(this) {
PLAYER_NUMBER -> R.string.number_of_players PLAYER_NUMBER -> R.string.number_of_players
COMMENT -> R.string.comment COMMENT -> R.string.comment
ANTE -> R.string.ante ANTE -> R.string.ante
BIG_BLIND_ANTE, BIG_BLIND_ANTE_READ -> R.string.bb_ante_option BIG_BLIND_ANTE, BIG_BLIND_ANTE_READ -> R.string.bb_ante_option
SETTINGS_HEADER -> R.string.settings SETTINGS_HEADER -> R.string.settings
else -> null else -> null
} }
} }
@ -91,8 +80,8 @@ enum class HandRowType(var layoutRes: Int) : ViewIdentifier, RowRepresentable {
override val imageRes: Int? override val imageRes: Int?
get() { get() {
return when(this) { return when(this) {
COMMENT -> R.drawable.picto_comment COMMENT -> R.drawable.picto_comment
SETTINGS_HEADER -> R.drawable.ic_settings SETTINGS_HEADER -> R.drawable.ic_settings
else -> null else -> null
} }
} }
@ -103,8 +92,9 @@ enum class HandRowType(var layoutRes: Int) : ViewIdentifier, RowRepresentable {
} }
class EditorAdapter( class EditorAdapter(
override var dataSource: RowRepresentableDataSource, override var dataSource: RowRepresentableDataSource,
override var delegate: RowRepresentableDelegate? = null) : override var delegate: RowRepresentableDelegate? = null
) :
RecyclerView.Adapter<RecyclerView.ViewHolder>(), RecyclerView.Adapter<RecyclerView.ViewHolder>(),
RecyclerAdapter { RecyclerAdapter {
@ -116,21 +106,21 @@ class EditorAdapter(
val rowType: HandRowType = HandRowType.values()[viewType] val rowType: HandRowType = HandRowType.values()[viewType]
val layout = LayoutInflater.from(parent.context).inflate(rowType.layoutRes, parent, false) val layout = LayoutInflater.from(parent.context).inflate(rowType.layoutRes, parent, false)
return when (rowType) { return when (rowType) {
HandRowType.DEFAULT -> RowViewHolder(layout) HandRowType.DEFAULT -> RowViewHolder(layout)
HandRowType.HEADER -> RowViewHolder(layout) HandRowType.HEADER -> RowViewHolder(layout)
HandRowType.SETTINGS_HEADER -> RowViewHolder(layout) HandRowType.SETTINGS_HEADER -> RowViewHolder(layout)
HandRowType.ACTION -> RowActionHolder(layout) HandRowType.ACTION -> RowActionHolder(layout)
HandRowType.STREET -> RowStreetHolder(layout) HandRowType.STREET -> RowStreetHolder(layout)
HandRowType.PLAYER_SUMMARY -> RowPlayerSummaryHolder(layout) HandRowType.PLAYER_SUMMARY -> RowPlayerSummaryHolder(layout)
HandRowType.STRADDLE -> RowStraddleHolder(layout) HandRowType.STRADDLE -> RowStraddleHolder(layout)
HandRowType.PLAYER_SETUP -> RowPlayerSetupHolder(layout) HandRowType.PLAYER_SETUP -> RowPlayerSetupHolder(layout)
HandRowType.PLAYER_SETUP_READ -> RowReadOnlyPlayerSetupHolder(layout) HandRowType.PLAYER_SETUP_READ -> RowReadOnlyPlayerSetupHolder(layout)
HandRowType.COMMENT -> RowViewHolder(layout) HandRowType.COMMENT -> RowViewHolder(layout)
HandRowType.ACTION_READ -> RowActionReadHolder(layout) HandRowType.ACTION_READ -> RowActionReadHolder(layout)
HandRowType.HERO_POSITION, HandRowType.PLAYER_POSITION -> RowPositionHolder(layout) HandRowType.HERO_POSITION, HandRowType.PLAYER_POSITION -> RowPositionHolder(layout)
HandRowType.PLAYER_NUMBER, HandRowType.PLAYER_NUMBER,
HandRowType.ANTE, HandRowType.ANTE,
HandRowType.BIG_BLIND_ANTE, HandRowType.BIG_BLIND_ANTE_READ -> RowViewHolder(layout) HandRowType.BIG_BLIND_ANTE, HandRowType.BIG_BLIND_ANTE_READ -> RowViewHolder(layout)
} }
} }
@ -180,15 +170,27 @@ class EditorAdapter(
this.currentPosition = position this.currentPosition = position
} }
protected fun configureEditTexts(index: Int, position: Int, row: RowRepresentable, adapter: RecyclerAdapter) { protected fun configureEditTexts(
index: Int,
position: Int,
row: RowRepresentable,
adapter: RecyclerAdapter
) {
this.configureEditTexts(index..index, position, row, adapter) this.configureEditTexts(index..index, position, row, adapter)
} }
private fun configureEditTexts(tagRange: IntRange, position: Int, row: RowRepresentable, adapter: RecyclerAdapter) { private fun configureEditTexts(
tagRange: IntRange,
position: Int,
row: RowRepresentable,
adapter: RecyclerAdapter
) {
tagRange.forEach { tag -> tagRange.forEach { tag ->
val editText = itemView.findViewWithTag<EditText>(tag) ?: throw PAIllegalStateException("Edit Text not found for tag: $tag, class: $this") val editText = itemView.findViewWithTag<EditText>(tag) ?: throw PAIllegalStateException(
"Edit Text not found for tag: $tag, class: $this"
)
// hides soft input view // hides soft input view
editText.setTextIsSelectable(true) editText.setTextIsSelectable(true)
@ -229,7 +231,9 @@ class EditorAdapter(
} }
protected fun configureTextView(tag: Int, row: RowRepresentable, adapter: RecyclerAdapter) { protected fun configureTextView(tag: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
val textView = itemView.findViewWithTag<TextView>(tag) ?: throw PAIllegalStateException("TextView not found for tag: $tag, class: $this") val textView = itemView.findViewWithTag<TextView>(tag) ?: throw PAIllegalStateException(
"TextView not found for tag: $tag, class: $this"
)
textView.text = adapter.dataSource.charSequenceForRow(row, itemView.context, tag) textView.text = adapter.dataSource.charSequenceForRow(row, itemView.context, tag)
} }
@ -287,7 +291,11 @@ class EditorAdapter(
return itemView.findViewWithTag(tag) return itemView.findViewWithTag(tag)
} }
protected fun configurePlayerImage(playerImageView: PlayerImageView, position: Int, row: RowRepresentable) { protected fun configurePlayerImage(
playerImageView: PlayerImageView,
position: Int,
row: RowRepresentable
) {
// Player // Player
val listener = View.OnClickListener { val listener = View.OnClickListener {
@ -359,6 +367,8 @@ class EditorAdapter(
} }
inner class RowStraddleHolder(itemView: View) : RowHandHolder(itemView) { inner class RowStraddleHolder(itemView: View) : RowHandHolder(itemView) {
private var container: ViewGroup = itemView.findViewById(R.id.container)
private var positionsChipGroup: FlowLayout = itemView.findViewById(R.id.positionsChipGroup)
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) { override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
super.onBind(position, row, adapter) super.onBind(position, row, adapter)
@ -366,10 +376,14 @@ class EditorAdapter(
val straddleRow = row as StraddleRowRepresentable val straddleRow = row as StraddleRowRepresentable
adapter.dataSource.backgroundColor(position, row)?.let { color -> adapter.dataSource.backgroundColor(position, row)?.let { color ->
itemView.findViewById<ViewGroup>(R.id.container)?.setBackgroundColor(itemView.context.getColor(color)) this.container.setBackgroundColor(
itemView.context.getColor(
color
)
)
} }
itemView.positionsChipGroup.removeAllViews() this.positionsChipGroup.removeAllViews()
straddleRow.positions.forEach { pos -> straddleRow.positions.forEach { pos ->
val chip = Chip(itemView.context) val chip = Chip(itemView.context)
@ -388,20 +402,21 @@ class EditorAdapter(
} }
adapter.delegate?.onRowValueChanged(straddleRow.selectedPositions, row) adapter.delegate?.onRowValueChanged(straddleRow.selectedPositions, row)
} }
itemView.positionsChipGroup.addView(chip) this.positionsChipGroup.addView(chip)
} }
} }
} }
inner class RowPositionHolder(itemView: View) : RowHandHolder(itemView) { inner class RowPositionHolder(itemView: View) : RowHandHolder(itemView) {
private var recycler: RecyclerView = itemView.findViewById(R.id.recycler)
private var positionAdapter: PositionAdapter = PositionAdapter() private var positionAdapter: PositionAdapter = PositionAdapter()
private var positionViewManager: LinearLayoutManager = private var positionViewManager: LinearLayoutManager =
LinearLayoutManager(itemView.context, RecyclerView.HORIZONTAL, false) LinearLayoutManager(itemView.context, RecyclerView.HORIZONTAL, false)
init { init {
itemView.recycler.apply { this.recycler.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = positionViewManager layoutManager = positionViewManager
adapter = positionAdapter adapter = positionAdapter
@ -411,7 +426,11 @@ class EditorAdapter(
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) { override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
super.onBind(position, row, adapter) super.onBind(position, row, adapter)
this.positionAdapter.positions = adapter.dataSource.contentForRow(row, itemView.context, Position::class) this.positionAdapter.positions = adapter.dataSource.contentForRow(
row,
itemView.context,
Position::class
)
this.positionAdapter.setOnClickListener { pos -> this.positionAdapter.setOnClickListener { pos ->
adapter.delegate?.onRowValueChanged(pos, row) adapter.delegate?.onRowValueChanged(pos, row)
this.positionAdapter.notifyDataSetChanged() this.positionAdapter.notifyDataSetChanged()
@ -427,26 +446,33 @@ class EditorAdapter(
inner class RowActionReadHolder(itemView: View) : RowHandHolder(itemView) { inner class RowActionReadHolder(itemView: View) : RowHandHolder(itemView) {
init { private var playerImage: PlayerImageView = itemView.findViewById(R.id.player_image_rhar)
itemView.player_image_rhar.tag = ActionReadRow.Tag.PLAYER.ordinal private var stackText: TextView = itemView.findViewById(R.id.stackText)
itemView.stackText.tag = ActionReadRow.Tag.STACK.ordinal private var playersText: TextView = itemView.findViewById(R.id.playersText)
private var actionText: TextView = itemView.findViewById(R.id.actionText)
private var actionContainer: View = itemView.findViewById(R.id.action_container)
private var amountText: TextView = itemView.findViewById(R.id.amountText)
init {
playerImage.tag = ActionReadRow.Tag.PLAYER.ordinal
stackText.tag = ActionReadRow.Tag.STACK.ordinal
} }
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) { override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
configurePlayerImage(itemView.player_image_rhar, position, row) configurePlayerImage(this.playerImage, position, row)
val actionReadRow = row as ActionReadRow val actionReadRow = row as ActionReadRow
itemView.playersText.text = actionReadRow.positions.joinToString(", ") { it.value } this.playersText.text = actionReadRow.positions.joinToString(", ") { it.value }
actionReadRow.action?.let { type -> actionReadRow.action?.let { type ->
itemView.actionText.text = type.localizedTitle(itemView.context) this.actionText.text = type.localizedTitle(itemView.context)
val background = itemView.context.getDrawable(type.background) val background = itemView.context.getDrawable(type.background)
itemView.action_container.background = background this.actionContainer.background = background
} }
itemView.amountText.text = actionReadRow.amount?.formatted this.amountText.text = actionReadRow.amount?.formatted
itemView.stackText.text = actionReadRow.stack?.formatted this.stackText.text = actionReadRow.stack?.formatted
} }
} }
@ -456,36 +482,42 @@ class EditorAdapter(
*/ */
inner class RowActionHolder(itemView: View) : RowHandHolder(itemView) { inner class RowActionHolder(itemView: View) : RowHandHolder(itemView) {
init { private var playerImage: PlayerImageView = itemView.findViewById(R.id.player_image_rha)
itemView.player_image_rha.tag = ComputedAction.Tag.PLAYER.ordinal private var actionButton: AppCompatButton = itemView.findViewById(R.id.actionButton)
itemView.actionButton.tag = ComputedAction.Tag.ACTION.ordinal private var amountEditText: EditText = itemView.findViewById(R.id.amountEditText)
itemView.amountEditText.tag = ComputedAction.Tag.AMOUNT.ordinal private var positionButton: AppCompatButton = itemView.findViewById(R.id.positionButton)
init {
this.playerImage.tag = ComputedAction.Tag.PLAYER.ordinal
this.actionButton.tag = ComputedAction.Tag.ACTION.ordinal
this.amountEditText.tag = ComputedAction.Tag.AMOUNT.ordinal
// Action // Action
setOnClickListener(itemView.actionButton) setOnClickListener(this.actionButton)
// Amount // Amount
itemView.findViewById<EditText>(R.id.amountEditText)?.let { amountEditText -> this.amountEditText.let { amountEditText ->
amountEditText.inputType = InputType.TYPE_NUMBER_FLAG_DECIMAL amountEditText.inputType = InputType.TYPE_NUMBER_FLAG_DECIMAL
amountEditText.isFocusableInTouchMode = true amountEditText.isFocusableInTouchMode = true
amountEditText.setOnTouchListener { _, event -> amountEditText.setOnTouchListener { _, event ->
// Timber.d("=== event.action = ${event.action}") // Timber.d("=== event.action = ${event.action}")
if (event.action == MotionEvent.ACTION_UP) { if (event.action == MotionEvent.ACTION_UP) {
// Both are required, otherwise requestFocus() fails // Both are required, otherwise requestFocus() fails
amountEditText.isFocusable = true amountEditText.isFocusable = true
amountEditText.isFocusableInTouchMode = true amountEditText.isFocusableInTouchMode = true
amountEditText.requestFocus() amountEditText.requestFocus()
editTextSelected(amountEditText) editTextSelected(amountEditText)
} }
return@setOnTouchListener true return@setOnTouchListener true
} }
} }
} }
private fun positionColor(isFocused: Boolean) : Int { private fun positionColor(isFocused: Boolean) : Int {
@ -498,17 +530,17 @@ class EditorAdapter(
val computedAction = row as ComputedAction val computedAction = row as ComputedAction
configurePlayerImage(itemView.player_image_rha, position, row) configurePlayerImage(this.playerImage, position, row)
// Position // Position
itemView.findViewById<Button>(R.id.positionButton)?.let { button -> this.positionButton.let { button ->
button.text = computedAction.position.value button.text = computedAction.position.value
// button.setBackgroundColor(color(computedAction.isHero)) // button.setBackgroundColor(color(computedAction.isHero))
button.backgroundTintList = ColorStateList.valueOf(positionColor(computedAction.isHero)) button.backgroundTintList = ColorStateList.valueOf(positionColor(computedAction.isHero))
} }
// Action // Action
itemView.findViewById<Button>(R.id.actionButton)?.let { actionButton -> this.actionButton.let { actionButton ->
actionButton.isEnabled = adapter.dataSource.isEnabled(row, actionButton.tag as Int) actionButton.isEnabled = adapter.dataSource.isEnabled(row, actionButton.tag as Int)
val selected = adapter.dataSource.isSelected(position, row, actionButton.tag as Int) val selected = adapter.dataSource.isSelected(position, row, actionButton.tag as Int)
@ -523,7 +555,7 @@ class EditorAdapter(
} }
// Amount // Amount
itemView.findViewById<EditText>(R.id.amountEditText)?.let { amountEditText -> this.amountEditText.let { amountEditText ->
val tag = amountEditText.tag as Int val tag = amountEditText.tag as Int
configureEditTexts(tag, position, row, adapter) configureEditTexts(tag, position, row, adapter)
} }
@ -536,14 +568,15 @@ class EditorAdapter(
* Display a hand street * Display a hand street
*/ */
inner class RowStreetHolder(itemView: View) : RowHandHolder(itemView) { inner class RowStreetHolder(itemView: View) : RowHandHolder(itemView) {
private var cardsLayout: LinearLayout = itemView.findViewById(R.id.cardsLayout)
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) { override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
super.onBind(position, row, adapter) super.onBind(position, row, adapter)
val streetCardsRow = row as StreetCardsRow val streetCardsRow = row as StreetCardsRow
itemView.cardsLayout.tag = streetCardsRow.street.ordinal this.cardsLayout.tag = streetCardsRow.street.ordinal
configureCardsLayout(itemView.cardsLayout, true) configureCardsLayout(this.cardsLayout, true)
} }
@ -553,10 +586,12 @@ class EditorAdapter(
* Display a hand action * Display a hand action
*/ */
inner class RowPlayerSummaryHolder(itemView: View) : RowHandHolder(itemView) { inner class RowPlayerSummaryHolder(itemView: View) : RowHandHolder(itemView) {
private var hpsPlayerImage: PlayerImageView = itemView.findViewById(R.id.hps_player_image)
private var handLayout: LinearLayout = itemView.findViewById(R.id.handLayout)
init { init {
itemView.hps_player_image.tag = PlayerCardsRow.Tag.PLAYER.ordinal this.hpsPlayerImage.tag = PlayerCardsRow.Tag.PLAYER.ordinal
itemView.handLayout.tag = PlayerCardsRow.Tag.CARDS.ordinal this.handLayout.tag = PlayerCardsRow.Tag.CARDS.ordinal
} }
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) { override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
@ -571,18 +606,20 @@ class EditorAdapter(
positionButton.setBackgroundColor(color(playerCardView.isHero)) positionButton.setBackgroundColor(color(playerCardView.isHero))
} }
configurePlayerImage(itemView.hps_player_image, position, row) configurePlayerImage(this.hpsPlayerImage, position, row)
configureCardsLayout(itemView.handLayout as LinearLayout, false) configureCardsLayout(this.handLayout, false)
} }
} }
abstract inner class AbstractRowPlayerSetup(itemView: View) : RowHandHolder(itemView) { abstract inner class AbstractRowPlayerSetup(itemView: View) : RowHandHolder(itemView) {
private var psHandLayout: LinearLayout = itemView.findViewById(R.id.ps_hand_layout)
private var positionButton: AppCompatButton = itemView.findViewById(R.id.position_button)
protected var delegate: RowRepresentableDelegate? = null protected var delegate: RowRepresentableDelegate? = null
init { init {
itemView.ps_hand_layout.tag = PlayerSetupRow.Tag.HAND.ordinal this.psHandLayout.tag = PlayerSetupRow.Tag.HAND.ordinal
} }
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) { override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
@ -591,22 +628,28 @@ class EditorAdapter(
this.delegate = adapter.delegate this.delegate = adapter.delegate
// Position Button // Position Button
itemView.position_button.text = adapter.dataSource.charSequenceForRow(row, itemView.context, PlayerSetupRow.Tag.POSITION.ordinal) this.positionButton.text = adapter.dataSource.charSequenceForRow(
row,
itemView.context,
PlayerSetupRow.Tag.POSITION.ordinal
)
val positionalRow = row as PositionalRow val positionalRow = row as PositionalRow
itemView.position_button.backgroundTintList = ColorStateList.valueOf(color(positionalRow.isHero)) this.positionButton.backgroundTintList = ColorStateList.valueOf(color(positionalRow.isHero))
configureCardsLayout(itemView.ps_hand_layout as LinearLayout, false) configureCardsLayout(this.psHandLayout, false)
} }
} }
inner class RowReadOnlyPlayerSetupHolder(itemView: View) : AbstractRowPlayerSetup(itemView) { inner class RowReadOnlyPlayerSetupHolder(itemView: View) : AbstractRowPlayerSetup(itemView) {
private var psPlayerImage: PlayerImageView = itemView.findViewById(R.id.ps_player_image)
private var stackTextView: TextView = itemView.findViewById(R.id.stack_text_view)
init { init {
itemView.ps_player_image.tag = PlayerSetupRow.Tag.PLAYER.ordinal this.psPlayerImage.tag = PlayerSetupRow.Tag.PLAYER.ordinal
itemView.stack_text_view.tag = PlayerSetupRow.Tag.STACK.ordinal this.stackTextView.tag = PlayerSetupRow.Tag.STACK.ordinal
} }
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) { override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
@ -615,23 +658,27 @@ class EditorAdapter(
configureTextView(PlayerSetupRow.Tag.STACK.ordinal, row, adapter) configureTextView(PlayerSetupRow.Tag.STACK.ordinal, row, adapter)
// Player // Player
configurePlayerImage(itemView.ps_player_image, position, row as PlayerSetupRow) configurePlayerImage(this.psPlayerImage, position, row as PlayerSetupRow)
} }
} }
inner class RowPlayerSetupHolder(itemView: View) : AbstractRowPlayerSetup(itemView) { inner class RowPlayerSetupHolder(itemView: View) : AbstractRowPlayerSetup(itemView) {
private var playerImage: PlayerImageView = itemView.findViewById(R.id.player_image)
private var positionButton: AppCompatButton = itemView.findViewById(R.id.position_button)
private var psHandLayout: LinearLayout = itemView.findViewById(R.id.ps_hand_layout)
private var stackEditText: EditText = itemView.findViewById(R.id.stack_edit_text)
init { init {
itemView.player_image.tag = PlayerSetupRow.Tag.PLAYER.ordinal this.playerImage.tag = PlayerSetupRow.Tag.PLAYER.ordinal
itemView.position_button.tag = PlayerSetupRow.Tag.POSITION.ordinal this.positionButton.tag = PlayerSetupRow.Tag.POSITION.ordinal
itemView.ps_hand_layout.tag = PlayerSetupRow.Tag.HAND.ordinal this.psHandLayout.tag = PlayerSetupRow.Tag.HAND.ordinal
itemView.stack_edit_text.tag = PlayerSetupRow.Tag.STACK.ordinal this.stackEditText.tag = PlayerSetupRow.Tag.STACK.ordinal
itemView.stack_edit_text.inputType = InputType.TYPE_NUMBER_FLAG_DECIMAL this.stackEditText.inputType = InputType.TYPE_NUMBER_FLAG_DECIMAL
setClickListener(itemView.stack_edit_text) setClickListener(this.stackEditText)
setOnItemClickListener(itemView.position_button, false) setOnItemClickListener(this.positionButton, false)
} }
@ -639,7 +686,7 @@ class EditorAdapter(
super.onBind(position, row, adapter) super.onBind(position, row, adapter)
// Player // Player
configurePlayerImage(itemView.player_image, position, row) configurePlayerImage(this.playerImage, position, row)
configureEditTexts(PlayerSetupRow.Tag.STACK.ordinal, position, row, adapter) configureEditTexts(PlayerSetupRow.Tag.STACK.ordinal, position, row, adapter)
} }

@ -11,9 +11,8 @@ import android.view.animation.AccelerateDecelerateInterpolator
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import kotlinx.android.synthetic.main.fragment_hand_history.*
import kotlinx.android.synthetic.main.fragment_settings.recyclerView
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentHandHistoryBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.handhistory.Position import net.pokeranalytics.android.model.handhistory.Position
@ -68,6 +67,9 @@ class EditorFragment : RealmFragment(), RowRepresentableDelegate, KeyboardListen
return this.model.isEdited return this.model.isEdited
} }
private var _binding: FragmentHandHistoryBinding? = null
private val binding get() = _binding!!
companion object { companion object {
fun newInstance(id: String? = null, configurationId: String? = null, attached: Boolean = false): EditorFragment { fun newInstance(id: String? = null, configurationId: String? = null, attached: Boolean = false): EditorFragment {
@ -91,9 +93,10 @@ class EditorFragment : RealmFragment(), RowRepresentableDelegate, KeyboardListen
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_hand_history, container, false) _binding = FragmentHandHistoryBinding.inflate(inflater, container, false)
return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -137,7 +140,7 @@ class EditorFragment : RealmFragment(), RowRepresentableDelegate, KeyboardListen
// } // }
// val itemTouchHelper = ItemTouchHelper(swipeToDelete) // val itemTouchHelper = ItemTouchHelper(swipeToDelete)
recyclerView.apply { binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = SmoothScrollLinearLayoutManager(requireContext()) layoutManager = SmoothScrollLinearLayoutManager(requireContext())
adapter = editorAdapter adapter = editorAdapter
@ -156,7 +159,7 @@ class EditorFragment : RealmFragment(), RowRepresentableDelegate, KeyboardListen
// At first, the selection is defined before the holder is bound, // At first, the selection is defined before the holder is bound,
// so we retrieve the editText inputConnection once the recycler view has been rendered // so we retrieve the editText inputConnection once the recycler view has been rendered
this.recyclerView.viewTreeObserver.addOnGlobalLayoutListener { this.binding.recyclerView.viewTreeObserver.addOnGlobalLayoutListener {
when (this.model.currentKeyboard) { when (this.model.currentKeyboard) {
HHKeyboard.AMOUNT -> { HHKeyboard.AMOUNT -> {
val selection = this.model.currentSelection val selection = this.model.currentSelection
@ -168,7 +171,7 @@ class EditorFragment : RealmFragment(), RowRepresentableDelegate, KeyboardListen
} }
initKeyboardDefaultHeight() initKeyboardDefaultHeight()
this.keyboard.keyboardListener = this this.binding.keyboard.keyboardListener = this
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
@ -227,6 +230,11 @@ class EditorFragment : RealmFragment(), RowRepresentableDelegate, KeyboardListen
return true return true
} }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
private fun showReplayer() { private fun showReplayer() {
(this.activity as HandHistoryActivity).showReplayer(this.model.handHistory.id) (this.activity as HandHistoryActivity).showReplayer(this.model.handHistory.id)
} }
@ -295,10 +303,10 @@ class EditorFragment : RealmFragment(), RowRepresentableDelegate, KeyboardListen
val handRow = this.model.rowRepresentableForPosition(selection.index) as? HandHistoryRow val handRow = this.model.rowRepresentableForPosition(selection.index) as? HandHistoryRow
val holder = val holder =
recyclerView.findViewHolderForAdapterPosition(selection.index) as? EditorAdapter.RowHandHolder binding.recyclerView.findViewHolderForAdapterPosition(selection.index) as? EditorAdapter.RowHandHolder
holder?.let { holder?.let {
val amountEditText = it.editTextForTag(selection.tag) val amountEditText = it.editTextForTag(selection.tag)
this.keyboard.setAmountEditText( this.binding.keyboard.setAmountEditText(
amountEditText, amountEditText,
handRow?.amountForTag(this.model.handHistory, selection.tag) handRow?.amountForTag(this.model.handHistory, selection.tag)
) )
@ -541,10 +549,10 @@ class EditorFragment : RealmFragment(), RowRepresentableDelegate, KeyboardListen
*/ */
private fun configureActionKeyboard() { private fun configureActionKeyboard() {
val availableActions = this.model.availableActions() val availableActions = this.model.availableActions()
this.keyboard.setAvailableAction(availableActions) this.binding.keyboard.setAvailableAction(availableActions)
val positions = this.model.positionsToAct() val positions = this.model.positionsToAct()
this.keyboard.setPositions(positions) this.binding.keyboard.setPositions(positions)
} }
/*** /***
@ -579,7 +587,7 @@ class EditorFragment : RealmFragment(), RowRepresentableDelegate, KeyboardListen
* We subtract 1 to give space and the ability to see the previously entered data * We subtract 1 to give space and the ability to see the previously entered data
*/ */
private fun scrollToPosition(index: Int) { private fun scrollToPosition(index: Int) {
this.recyclerView.smoothScrollToPosition(index - 1) this.binding.recyclerView.smoothScrollToPosition(index - 1)
} }
/*** /***
@ -606,11 +614,11 @@ class EditorFragment : RealmFragment(), RowRepresentableDelegate, KeyboardListen
*/ */
private fun showKeyboard(keyboard: HHKeyboard, endHandler: (() -> (Unit))? = null) { private fun showKeyboard(keyboard: HHKeyboard, endHandler: (() -> (Unit))? = null) {
val lp = this.kbTopGuideline.layoutParams as ConstraintLayout.LayoutParams val lp = this.binding.kbTopGuideline.layoutParams as ConstraintLayout.LayoutParams
if (lp.guideEnd == 0) { if (lp.guideEnd == 0) {
this.animateKeyboard(true, endHandler) this.animateKeyboard(true, endHandler)
} }
this.keyboard.show(keyboard) this.binding.keyboard.show(keyboard)
} }
/*** /***
@ -631,11 +639,11 @@ class EditorFragment : RealmFragment(), RowRepresentableDelegate, KeyboardListen
// set interpolator and updateListener to get the animated value // set interpolator and updateListener to get the animated value
valueAnimator.addUpdateListener { valueAnimator.addUpdateListener {
val lp = this.kbTopGuideline.layoutParams as ConstraintLayout.LayoutParams val lp = this.binding.kbTopGuideline.layoutParams as ConstraintLayout.LayoutParams
// get the float value // get the float value
lp.guideEnd = (it.animatedValue as Float).toInt() lp.guideEnd = (it.animatedValue as Float).toInt()
// update layout params // update layout params
this.kbTopGuideline.layoutParams = lp this.binding.kbTopGuideline.layoutParams = lp
if (lp.guideEnd == end.toInt()) { if (lp.guideEnd == end.toInt()) {
endHandler?.invoke() endHandler?.invoke()
@ -649,7 +657,7 @@ class EditorFragment : RealmFragment(), RowRepresentableDelegate, KeyboardListen
* Starts by hiding the keyboard * Starts by hiding the keyboard
*/ */
private fun initKeyboardDefaultHeight() { private fun initKeyboardDefaultHeight() {
val lp = this.kbTopGuideline.layoutParams as ConstraintLayout.LayoutParams val lp = this.binding.kbTopGuideline.layoutParams as ConstraintLayout.LayoutParams
lp.guideEnd = 0 lp.guideEnd = 0
} }

@ -8,8 +8,8 @@ import android.widget.PopupWindow
import android.widget.Switch import android.widget.Switch
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import io.realm.Sort import io.realm.Sort
import kotlinx.android.synthetic.main.fragment_replayer.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentReplayerBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.realm.handhistory.HandHistory import net.pokeranalytics.android.model.realm.handhistory.HandHistory
import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.ui.fragment.components.RealmFragment
@ -38,6 +38,9 @@ class ReplayerFragment : RealmFragment() {
*/ */
private lateinit var model: ReplayerModel private lateinit var model: ReplayerModel
private var _binding: FragmentReplayerBinding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -47,9 +50,10 @@ class ReplayerFragment : RealmFragment() {
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_replayer, container, false) _binding = FragmentReplayerBinding.inflate(inflater, container, false)
return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -79,6 +83,11 @@ class ReplayerFragment : RealmFragment() {
} }
} }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
private fun initData() { private fun initData() {
val id = arguments?.getString(BundleKey.HAND_HISTORY_ID.value) ?: throw PAIllegalStateException("Attempt to start a replayer without hh id") val id = arguments?.getString(BundleKey.HAND_HISTORY_ID.value) ?: throw PAIllegalStateException("Attempt to start a replayer without hh id")
val hh = getRealm().findById<HandHistory>(id) ?: throw PAIllegalStateException("hh with id: $id not found") val hh = getRealm().findById<HandHistory>(id) ?: throw PAIllegalStateException("hh with id: $id not found")
@ -86,25 +95,25 @@ class ReplayerFragment : RealmFragment() {
} }
private fun initUI() { private fun initUI() {
this.next_action.setOnClickListener { this.binding.nextAction.setOnClickListener {
nextAction() nextAction()
} }
this.previous_action.setOnClickListener { this.binding.previousAction.setOnClickListener {
previousAction() previousAction()
} }
this.next_hand.setOnClickListener { this.binding.nextHand.setOnClickListener {
nextHand() nextHand()
} }
this.previous_hand.setOnClickListener { this.binding.previousHand.setOnClickListener {
previousHand() previousHand()
} }
this.play_pause.setOnClickListener { this.binding.playPause.setOnClickListener {
playOrPause() playOrPause()
} }
this.speed.setOnClickListener { this.binding.speed.setOnClickListener {
changeSpeed() changeSpeed()
} }
this.settings.setOnClickListener { this.binding.settings.setOnClickListener {
openSettings() openSettings()
} }
@ -131,12 +140,12 @@ class ReplayerFragment : RealmFragment() {
private fun updateSpeedButtonText() { private fun updateSpeedButtonText() {
val speedText = "${this.model.speedMultiplier.value}x" val speedText = "${this.model.speedMultiplier.value}x"
this.speed.text = speedText this.binding.speed.text = speedText
} }
private fun loadHand(handHistory: HandHistory) { private fun loadHand(handHistory: HandHistory) {
val config = ReplayerAnimator(handHistory, false) val config = ReplayerAnimator(handHistory, false)
this.replayer.animator = config this.binding.replayer.animator = config
this.model.animator = config this.model.animator = config
} }
@ -164,18 +173,18 @@ class ReplayerFragment : RealmFragment() {
this.mainHandler.postDelayed(timerRunnable, 0L) this.mainHandler.postDelayed(timerRunnable, 0L)
this.model.isPlaying = true this.model.isPlaying = true
this.play_pause.setImageResource(R.drawable.ic_outline_pause) this.binding.playPause.setImageResource(R.drawable.ic_outline_pause)
} }
private fun pause() { private fun pause() {
this.mainHandler.removeCallbacks(timerRunnable) this.mainHandler.removeCallbacks(timerRunnable)
this.model.isPlaying = false this.model.isPlaying = false
this.play_pause.setImageResource(R.drawable.ic_play_arrow) this.binding.playPause.setImageResource(R.drawable.ic_play_arrow)
} }
private fun nextAction() { private fun nextAction() {
this.model.nextStep() this.model.nextStep()
this.replayer.refresh() this.binding.replayer.refresh()
if (this.model.isPlaying) { if (this.model.isPlaying) {
this.mainHandler.postDelayed(timerRunnable, this.model.actionDelay) this.mainHandler.postDelayed(timerRunnable, this.model.actionDelay)
@ -185,7 +194,7 @@ class ReplayerFragment : RealmFragment() {
private fun previousAction() { private fun previousAction() {
this.model.previousStep() this.model.previousStep()
this.replayer.refresh() this.binding.replayer.refresh()
refreshPlayButtonIfNecessary() refreshPlayButtonIfNecessary()
} }
@ -237,13 +246,13 @@ class ReplayerFragment : RealmFragment() {
switch.isChecked = Preferences.getShowVillainCards(requireContext()) switch.isChecked = Preferences.getShowVillainCards(requireContext())
switch.setOnCheckedChangeListener { _, isChecked -> switch.setOnCheckedChangeListener { _, isChecked ->
Preferences.setShowVillainCards(isChecked, requireContext()) Preferences.setShowVillainCards(isChecked, requireContext())
this.replayer.refresh() this.binding.replayer.refresh()
} }
val popupWindow = PopupWindow(requireContext()) val popupWindow = PopupWindow(requireContext())
popupWindow.contentView = view popupWindow.contentView = view
popupWindow.isFocusable = true popupWindow.isFocusable = true
popupWindow.showAsDropDown(this.settings, 0, -300) popupWindow.showAsDropDown(this.binding.settings, 0, -300)
} }

@ -2,10 +2,10 @@ package net.pokeranalytics.android.ui.modules.handhistory.views
import android.content.Context import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.ImageButton
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.view_hand_keyboard_action.view.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.handhistory.Position import net.pokeranalytics.android.model.handhistory.Position
@ -26,10 +26,15 @@ class KeyboardActionView(context: Context) : AbstractKeyboardView(context),
private var availableActions: Set<Action.Type> = setOf() private var availableActions: Set<Action.Type> = setOf()
private var recyclerView: RecyclerView
private var closeButton: ImageButton
init { init {
LayoutInflater.from(context) val view = LayoutInflater.from(context)
.inflate(R.layout.view_hand_keyboard_action, this, true) .inflate(R.layout.view_hand_keyboard_action, this, true)
this.recyclerView = view.findViewById<RecyclerView>(R.id.recyclerView)
this.closeButton = view.findViewById<ImageButton>(R.id.closeButton)
// Action recycler // Action recycler
val spanCount = 3 val spanCount = 3
@ -39,15 +44,14 @@ class KeyboardActionView(context: Context) : AbstractKeyboardView(context),
val spacing = 2.px val spacing = 2.px
val includeEdge = false val includeEdge = false
this.recyclerView.apply { recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
adapter = dataAdapter adapter = dataAdapter
addItemDecoration(GridSpacingItemDecoration(spanCount, spacing, includeEdge)) addItemDecoration(GridSpacingItemDecoration(spanCount, spacing, includeEdge))
} }
closeButton.setOnClickListener {
this.closeButton.setOnClickListener {
this.keyboardListener?.closeKeyboard() this.keyboardListener?.closeKeyboard()
} }
@ -61,7 +65,7 @@ class KeyboardActionView(context: Context) : AbstractKeyboardView(context),
this.positionAdapter = PositionAdapter(it) this.positionAdapter = PositionAdapter(it)
} ?: throw PAIllegalStateException("keyboard listener not set") } ?: throw PAIllegalStateException("keyboard listener not set")
this.recycler.apply { recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = positionViewManager layoutManager = positionViewManager
adapter = positionAdapter adapter = positionAdapter
@ -74,7 +78,7 @@ class KeyboardActionView(context: Context) : AbstractKeyboardView(context),
this.positionAdapter.positions = positions this.positionAdapter.positions = positions
} }
override fun adapterRows(): List<RowRepresentable>? { override fun adapterRows(): List<RowRepresentable> {
return Action.Type.defaultTypes return Action.Type.defaultTypes
} }
@ -99,7 +103,7 @@ class KeyboardActionView(context: Context) : AbstractKeyboardView(context),
this.dataAdapter.notifyDataSetChanged() this.dataAdapter.notifyDataSetChanged()
} }
override fun textColor(position: Int, row: RowRepresentable): Int? { override fun textColor(position: Int, row: RowRepresentable): Int {
return if (isEnabled(row, 0)) { return if (isEnabled(row, 0)) {
R.color.white R.color.white
} else { } else {

@ -4,9 +4,11 @@ import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputConnection import android.view.inputmethod.InputConnection
import android.widget.Button
import android.widget.EditText import android.widget.EditText
import android.widget.ImageView
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import kotlinx.android.synthetic.main.view_hand_keyboard_amount.view.* import androidx.recyclerview.widget.RecyclerView
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
@ -17,7 +19,6 @@ import net.pokeranalytics.android.ui.view.GridSpacingItemDecoration
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.util.extensions.noGroupingFormatted import net.pokeranalytics.android.util.extensions.noGroupingFormatted
import timber.log.Timber
import java.text.DecimalFormatSymbols import java.text.DecimalFormatSymbols
class NumericKey : RowRepresentable { class NumericKey : RowRepresentable {
@ -77,9 +78,22 @@ class KeyboardAmountView(context: Context) : AbstractKeyboardView(context),
*/ */
private var inputConnection: InputConnection? = null private var inputConnection: InputConnection? = null
private var recyclerView: RecyclerView
private var nextButton: Button
private var kiloButton: Button
private var millionButton: Button
private var clearButton: Button
private var closeButton: ImageView
init { init {
LayoutInflater.from(context) val view = LayoutInflater.from(context)
.inflate(R.layout.view_hand_keyboard_amount, this, true) .inflate(R.layout.view_hand_keyboard_amount, this, true)
this.recyclerView = view.findViewById(R.id.recyclerView)
this.nextButton = view.findViewById(R.id.nextButton)
this.kiloButton = view.findViewById(R.id.kiloButton)
this.millionButton = view.findViewById(R.id.millionButton)
this.clearButton = view.findViewById(R.id.clearButton)
this.closeButton = view.findViewById(R.id.closeButton)
val viewManager = GridLayoutManager(context, 3) val viewManager = GridLayoutManager(context, 3)
this.dataAdapter = RowRepresentableAdapter(this, this) this.dataAdapter = RowRepresentableAdapter(this, this)
@ -142,7 +156,7 @@ class KeyboardAmountView(context: Context) : AbstractKeyboardView(context),
} }
override fun adapterRows(): List<RowRepresentable>? { override fun adapterRows(): List<RowRepresentable> {
val keys = mutableListOf<NumericKey>() val keys = mutableListOf<NumericKey>()
(0 until 12).forEach { index -> (0 until 12).forEach { index ->
val key = when (index) { val key = when (index) {

@ -2,8 +2,10 @@ package net.pokeranalytics.android.ui.modules.handhistory.views
import android.content.Context import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.Button
import android.widget.ImageButton
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import kotlinx.android.synthetic.main.view_hand_keyboard_card.view.* import androidx.recyclerview.widget.RecyclerView
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.realm.handhistory.Card import net.pokeranalytics.android.model.realm.handhistory.Card
@ -20,10 +22,24 @@ class KeyboardCardView(context: Context) : AbstractKeyboardView(context) {
private lateinit var cardValueAdapter: CardValueAdapter private lateinit var cardValueAdapter: CardValueAdapter
private lateinit var cardSuitAdapter: CardSuitAdapter private lateinit var cardSuitAdapter: CardSuitAdapter
private var valueRecyclerView: RecyclerView
private var suitRecyclerView: RecyclerView
private var nextButton: Button
private var backSpaceButton: Button
private var clearButton: Button
private var closeButton: ImageButton
init { init {
LayoutInflater.from(context) val view = LayoutInflater.from(context)
.inflate(R.layout.view_hand_keyboard_card, this, true) .inflate(R.layout.view_hand_keyboard_card, this, true)
this.valueRecyclerView = view.findViewById(R.id.valueRecyclerView)
this.suitRecyclerView = view.findViewById(R.id.suitRecyclerView)
this.backSpaceButton = view.findViewById(R.id.backSpaceButton)
this.nextButton = view.findViewById(R.id.nextButton)
this.clearButton = view.findViewById(R.id.clearButton)
this.closeButton = view.findViewById(R.id.closeButton)
this.nextButton.setOnClickListener { this.nextButton.setOnClickListener {
this.keyboardListener?.cardSelectionEnded() this.keyboardListener?.cardSelectionEnded()

@ -1,8 +1,10 @@
package net.pokeranalytics.android.ui.modules.handhistory.views package net.pokeranalytics.android.ui.modules.handhistory.views
import android.view.View import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.row_hand_history_view.view.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.handhistory.Street import net.pokeranalytics.android.model.handhistory.Street
import net.pokeranalytics.android.model.realm.handhistory.HandHistory import net.pokeranalytics.android.model.realm.handhistory.HandHistory
@ -23,13 +25,15 @@ class RowHandHistoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemVie
val handHistory = row as HandHistory val handHistory = row as HandHistory
itemView.cardsLayout.removeAllViews() val cardsLayout = itemView.findViewById<LinearLayout>(R.id.cardsLayout)
cardsLayout.removeAllViews()
handHistory.cardViews(itemView.context, itemView.cardsLayout).forEach { view -> handHistory.cardViews(itemView.context, cardsLayout).forEach { view ->
itemView.cardsLayout.addView(view) cardsLayout.addView(view)
} }
itemView.amount.text = handHistory.potSizeForStreet(Street.SUMMARY).formatted val amount = itemView.findViewById<TextView>(R.id.amount)
amount.text = handHistory.potSizeForStreet(Street.SUMMARY).formatted
val heroWins = handHistory.heroWins val heroWins = handHistory.heroWins
val colorId = when(heroWins) { val colorId = when(heroWins) {
@ -38,12 +42,14 @@ class RowHandHistoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemVie
else -> R.color.kaki_light else -> R.color.kaki_light
} }
itemView.amount.setTextColor(itemView.context.getColor(colorId)) amount.setTextColor(itemView.context.getColor(colorId))
val listener = View.OnClickListener { val listener = View.OnClickListener {
delegate?.onRowSelected(position, row) delegate?.onRowSelected(position, row)
} }
itemView.constraintLayout.setOnClickListener(listener)
val constraintLayout = itemView.findViewById<ConstraintLayout>(R.id.constraintLayout)
constraintLayout.setOnClickListener(listener)
} }
} }

@ -11,13 +11,13 @@ import androidx.appcompat.content.res.AppCompatResources
import androidx.interpolator.view.animation.FastOutSlowInInterpolator import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import kotlinx.android.synthetic.main.fragment_session.*
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager
import net.pokeranalytics.android.calculus.optimalduration.CashGameOptimalDurationCalculator import net.pokeranalytics.android.calculus.optimalduration.CashGameOptimalDurationCalculator
import net.pokeranalytics.android.databinding.FragmentSessionBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
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
@ -69,6 +69,9 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
} }
} }
private var _binding: FragmentSessionBinding? = null
private val binding get() = _binding!!
// private val coroutineContext: CoroutineContext // private val coroutineContext: CoroutineContext
// get() = Dispatchers.Main // get() = Dispatchers.Main
@ -93,9 +96,10 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_session, container, false) _binding = FragmentSessionBinding.inflate(inflater, container, false)
return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -104,28 +108,33 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
initUI() initUI()
} }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
/** /**
* Init UI * Init UI
*/ */
private fun initUI() { private fun initUI() {
toolbar.title = if (currentSession.isTournament()) getString(R.string.tournament) else getString(R.string.cash_game) binding.toolbar.title = if (currentSession.isTournament()) getString(R.string.tournament) else getString(R.string.cash_game)
collapsingToolbar.title = toolbar.title binding.collapsingToolbar.title = binding.toolbar.title
sessionAdapter = RowRepresentableAdapter(this, this) sessionAdapter = RowRepresentableAdapter(this, this)
recyclerView.adapter = sessionAdapter binding.recyclerView.adapter = sessionAdapter
updateSessionUI(true) updateSessionUI(true)
setDisplayHomeAsUpEnabled(true) setDisplayHomeAsUpEnabled(true)
val viewManager = SmoothScrollLinearLayoutManager(requireContext()) val viewManager = SmoothScrollLinearLayoutManager(requireContext())
recyclerView.apply { binding.recyclerView.apply {
setHasFixedSize(true) setHasFixedSize(true)
layoutManager = viewManager layoutManager = viewManager
} }
floatingActionButton.setOnClickListener { binding.floatingActionButton.setOnClickListener {
if (this.currentSession.isValidForSave()) { if (this.currentSession.isValidForSave()) {
sessionHasBeenUserCustomized = true sessionHasBeenUserCustomized = true
manageSessionState() manageSessionState()
@ -279,6 +288,7 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
val animationDuration = if (firstDisplay) 0L else 300L val animationDuration = if (firstDisplay) 0L else 300L
val floatingActionButton = binding.floatingActionButton
when (currentSession.getState()) { when (currentSession.getState()) {
SessionState.PENDING, SessionState.PLANNED -> { SessionState.PENDING, SessionState.PLANNED -> {
sessionMenu?.findItem(R.id.restart)?.isVisible = false sessionMenu?.findItem(R.id.restart)?.isVisible = false
@ -345,17 +355,18 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
* Update adapter UI * Update adapter UI
*/ */
private fun updateAdapterUI() { private fun updateAdapterUI() {
this.adapterRows()?.let {
val diffResult = DiffUtil.calculateDiff(RowRepresentableDiffCallback(it, oldRows))
sessionAdapter.updateRows(diffResult)
oldRows.clear() val rows = this.adapterRows()
oldRows.addAll(it)
val diffResult = DiffUtil.calculateDiff(RowRepresentableDiffCallback(rows, oldRows))
this.sessionAdapter.updateRows(diffResult)
this.oldRows.clear()
this.oldRows.addAll(rows)
// if (scrollToTop) { // if (scrollToTop) {
// recyclerView.smoothScrollToPosition(0) // recyclerView.smoothScrollToPosition(0)
// } // }
}
} }
/** /**
@ -373,7 +384,7 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
} }
currentSession.startOrContinue() currentSession.startOrContinue()
this.recyclerView.smoothScrollToPosition(0) binding.recyclerView.smoothScrollToPosition(0)
} }
SessionState.STARTED -> { SessionState.STARTED -> {
@ -493,7 +504,7 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
// this.rowRepresentationForCurrentState = this.updatedRowRepresentationForCurrentState(requireContext()) // this.rowRepresentationForCurrentState = this.updatedRowRepresentationForCurrentState(requireContext())
} }
override fun adapterRows(): List<RowRepresentable>? { override fun adapterRows(): List<RowRepresentable> {
return this.model.rows return this.model.rows
} }

@ -4,13 +4,13 @@ import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isVisible import androidx.core.view.isVisible
import kotlinx.android.synthetic.main.layout_legend_default.view.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.extensions.setTextFormat import net.pokeranalytics.android.ui.extensions.setTextFormat
import net.pokeranalytics.android.ui.fragment.GraphFragment import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.util.TextFormat import net.pokeranalytics.android.util.TextFormat
interface LegendContent interface LegendContent
@ -35,7 +35,7 @@ open class LegendView : FrameLayout {
// rightFormat: TextFormat? = null // rightFormat: TextFormat? = null
// ) : Values("", leftFormat, rightFormat) // ) : Values("", leftFormat, rightFormat)
private lateinit var legendLayout: ConstraintLayout protected lateinit var legendLayout: ConstraintLayout
/** /**
* Constructors * Constructors
@ -56,28 +56,43 @@ open class LegendView : FrameLayout {
return R.layout.layout_legend_default return R.layout.layout_legend_default
} }
protected lateinit var stat1Name: TextView
protected lateinit var stat2Name: TextView
protected lateinit var counter: TextView
protected lateinit var stat1Value: TextView
protected lateinit var stat2Value: TextView
protected lateinit var title: TextView
/** /**
* Init * Init
*/ */
private fun init() { protected open fun init() {
val layoutInflater = LayoutInflater.from(context) val layoutInflater = LayoutInflater.from(context)
legendLayout = layoutInflater.inflate(this.getResourceLayout(), this, false) as ConstraintLayout legendLayout = layoutInflater.inflate(this.getResourceLayout(), this, false) as ConstraintLayout
val layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) val layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
addView(legendLayout, layoutParams) addView(legendLayout, layoutParams)
this.stat1Name = legendLayout.findViewById(R.id.stat1Name)
this.stat2Name = legendLayout.findViewById(R.id.stat2Name)
this.counter = legendLayout.findViewById(R.id.counter)
this.stat1Value = legendLayout.findViewById(R.id.stat1Value)
this.stat2Value = legendLayout.findViewById(R.id.stat2Value)
this.title = legendLayout.findViewById(R.id.title)
} }
/** /**
* Set the stat data to the view * Set the stat data to the view
*/ */
open fun prepareWithStat(stat: Stat, counter: Int? = null, style: GraphFragment.Style) { open fun prepareWithStat(stat: Stat, counter: Int? = null, style: Graph.Style) {
when (style) { when (style) {
GraphFragment.Style.BAR -> { Graph.Style.BAR -> {
this.stat1Name.text = stat.localizedTitle(context) this.stat1Name.text = stat.localizedTitle(context)
this.stat2Name.text = context.getString(R.string.sessions) this.stat2Name.text = context.getString(R.string.sessions)
this.counter.isVisible = false this.counter.isVisible = false
} }
GraphFragment.Style.LINE -> { Graph.Style.LINE -> {
if (stat.graphSignificantIndividualValue) { if (stat.graphSignificantIndividualValue) {
this.stat1Name.text = stat.localizedTitle(context) this.stat1Name.text = stat.localizedTitle(context)
this.stat2Name.text = stat.cumulativeLabelResId(context) this.stat2Name.text = stat.cumulativeLabelResId(context)

@ -2,16 +2,12 @@ package net.pokeranalytics.android.ui.view
import android.content.Context import android.content.Context
import android.graphics.drawable.GradientDrawable import android.graphics.drawable.GradientDrawable
import kotlinx.android.synthetic.main.layout_legend_color.view.* import android.view.View
import kotlinx.android.synthetic.main.layout_legend_default.view.stat1Name
import kotlinx.android.synthetic.main.layout_legend_default.view.stat1Value
import kotlinx.android.synthetic.main.layout_legend_default.view.stat2Name
import kotlinx.android.synthetic.main.layout_legend_default.view.stat2Value
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.util.TextFormat
import net.pokeranalytics.android.ui.extensions.setTextFormat import net.pokeranalytics.android.ui.extensions.setTextFormat
import net.pokeranalytics.android.ui.fragment.GraphFragment import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.util.TextFormat
data class MultilineLegendValues( data class MultilineLegendValues(
var firstTitle: String, var firstTitle: String,
@ -22,11 +18,18 @@ data class MultilineLegendValues(
class MultiLineLegendView(context: Context) : LegendView(context = context) { class MultiLineLegendView(context: Context) : LegendView(context = context) {
private lateinit var coloredCircle: View
override fun init() {
super.init()
this.coloredCircle = legendLayout.findViewById(R.id.coloredCircle)
}
override fun getResourceLayout(): Int { override fun getResourceLayout(): Int {
return R.layout.layout_legend_color return R.layout.layout_legend_color
} }
override fun prepareWithStat(stat: Stat, counter: Int?, style: GraphFragment.Style) { override fun prepareWithStat(stat: Stat, counter: Int?, style: Graph.Style) {
} }
override fun setItemData(content: LegendContent, color: Int?) { override fun setItemData(content: LegendContent, color: Int?) {

@ -6,12 +6,14 @@ import android.graphics.drawable.GradientDrawable
import android.util.AttributeSet import android.util.AttributeSet
import android.util.TypedValue import android.util.TypedValue
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat.getColor import androidx.core.content.ContextCompat.getColor
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
import kotlinx.android.synthetic.main.view_player_image.view.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.Player import net.pokeranalytics.android.model.realm.Player
import net.pokeranalytics.android.ui.extensions.px import net.pokeranalytics.android.ui.extensions.px
@ -43,6 +45,12 @@ class PlayerImageView : FrameLayout {
private lateinit var playerImageView: ConstraintLayout private lateinit var playerImageView: ConstraintLayout
private lateinit var playerImage: ImageView
private lateinit var playerStroke: TextView
private lateinit var playerInitial: TextView
private lateinit var playerImageSelection: View
private var onImageClickListener: OnClickListener? = null private var onImageClickListener: OnClickListener? = null
/** /**
@ -68,6 +76,12 @@ class PlayerImageView : FrameLayout {
this.playerImageView = layoutInflater.inflate(R.layout.view_player_image, this, false) as ConstraintLayout this.playerImageView = layoutInflater.inflate(R.layout.view_player_image, this, false) as ConstraintLayout
val layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) val layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
addView(playerImageView, layoutParams) addView(playerImageView, layoutParams)
this.playerImage = this.playerImageView.findViewById(R.id.player_image)
this.playerStroke = this.playerImageView.findViewById(R.id.playerStroke)
this.playerInitial = this.playerImageView.findViewById(R.id.playerInitial)
this.playerImageSelection = this.playerImageView.findViewById(R.id.playerImageSelection)
} }
/** /**
@ -79,14 +93,14 @@ class PlayerImageView : FrameLayout {
player.picture?.let { picture -> player.picture?.let { picture ->
val rDrawable = RoundedBitmapDrawableFactory.create(resources, picture) val rDrawable = RoundedBitmapDrawableFactory.create(resources, picture)
rDrawable.isCircular = true rDrawable.isCircular = true
playerImageView.player_image.setImageDrawable(rDrawable) this.playerImage.setImageDrawable(rDrawable)
} ?: run { } ?: run {
playerImageView.playerStroke.background = ResourcesCompat.getDrawable(resources, R.drawable.circle_stroke_kaki, null) this.playerStroke.background = ResourcesCompat.getDrawable(resources, R.drawable.circle_stroke_kaki, null)
playerImageView.player_image.setImageDrawable(null) this.playerImage.setImageDrawable(null)
playerImageView.playerInitial.text = player.initials this.playerInitial.text = player.initials
playerImageView.playerInitial.setTextSize(TypedValue.COMPLEX_UNIT_SP, size.getFontSize()) this.playerInitial.setTextSize(TypedValue.COMPLEX_UNIT_SP, size.getFontSize())
} }
@ -99,17 +113,17 @@ class PlayerImageView : FrameLayout {
} }
// Stroke & initial // Stroke & initial
val drawable = this.playerImageView.playerStroke.background as GradientDrawable? val drawable = this.playerStroke.background as GradientDrawable?
drawable?.setStroke(size.getStrokeSize(), color) drawable?.setStroke(size.getStrokeSize(), color)
this.playerImageView.playerInitial.setTextColor(color) this.playerInitial.setTextColor(color)
// Click listener // Click listener
if (this.onImageClickListener != null) { if (this.onImageClickListener != null) {
this.playerImageView.playerImageSelection.setOnClickListener { this.playerImageSelection.setOnClickListener {
this.onImageClickListener?.onClick(it) this.onImageClickListener?.onClick(it)
} }
} else { } else {
this.playerImageView.playerImageSelection.background = null this.playerImageSelection.background = null
} }
} }
@ -127,12 +141,12 @@ class PlayerImageView : FrameLayout {
val color = getColor(context, res) val color = getColor(context, res)
val drawable = this.playerImageView.playerStroke.background as GradientDrawable? val drawable = this.playerStroke.background as GradientDrawable?
drawable?.setStroke(size.getStrokeSize(), color) drawable?.setStroke(size.getStrokeSize(), color)
this.playerImageView.playerInitial.text = text this.playerInitial.text = text
this.playerImageView.playerInitial.setTextColor(color) this.playerInitial.setTextColor(color)
this.playerImageView.playerInitial.setTextSize(TypedValue.COMPLEX_UNIT_SP, size.getFontSize()) this.playerInitial.setTextSize(TypedValue.COMPLEX_UNIT_SP, size.getFontSize())
} }
/** /**
@ -141,17 +155,17 @@ class PlayerImageView : FrameLayout {
fun setOnImageClickListener(onImageClickListener: OnClickListener) { fun setOnImageClickListener(onImageClickListener: OnClickListener) {
this.onImageClickListener = onImageClickListener this.onImageClickListener = onImageClickListener
this.playerImageView.playerImageSelection.setOnClickListener { this.playerImageSelection.setOnClickListener {
this.onImageClickListener?.onClick(it) this.onImageClickListener?.onClick(it)
} }
} }
fun clear(size: Size = Size.NORMAL) { fun clear(size: Size = Size.NORMAL) {
val drawable = this.playerImageView.playerStroke.background as GradientDrawable? val drawable = this.playerStroke.background as GradientDrawable?
drawable?.setStroke(size.getStrokeSize(), getColor(context, R.color.kaki)) drawable?.setStroke(size.getStrokeSize(), getColor(context, R.color.kaki))
this.playerImageView.playerInitial.text = null this.playerInitial.text = null
} }
} }

@ -15,9 +15,8 @@ import com.github.mikephil.charting.charts.LineChart
import com.github.mikephil.charting.data.* import com.github.mikephil.charting.data.*
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup import com.google.android.material.chip.ChipGroup
import kotlinx.android.synthetic.main.row_feed_session.view.*
import kotlinx.android.synthetic.main.row_transaction.view.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.AxisFormatting
import net.pokeranalytics.android.calculus.ComputedStat import net.pokeranalytics.android.calculus.ComputedStat
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager
@ -33,7 +32,6 @@ import net.pokeranalytics.android.ui.extensions.ChipGroupExtension
import net.pokeranalytics.android.ui.extensions.px import net.pokeranalytics.android.ui.extensions.px
import net.pokeranalytics.android.ui.extensions.setTextFormat import net.pokeranalytics.android.ui.extensions.setTextFormat
import net.pokeranalytics.android.ui.modules.bankroll.BankrollRowRepresentable import net.pokeranalytics.android.ui.modules.bankroll.BankrollRowRepresentable
import net.pokeranalytics.android.ui.graph.AxisFormatting
import net.pokeranalytics.android.ui.graph.setStyle import net.pokeranalytics.android.ui.graph.setStyle
import net.pokeranalytics.android.ui.modules.handhistory.views.RowHandHistoryViewHolder import net.pokeranalytics.android.ui.modules.handhistory.views.RowHandHistoryViewHolder
import net.pokeranalytics.android.ui.view.holder.RowViewHolder import net.pokeranalytics.android.ui.view.holder.RowViewHolder
@ -435,11 +433,13 @@ enum class RowViewType(private var layoutRes: Int) : ViewIdentifier {
inner class RowSessionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), inner class RowSessionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder { BindableHolder {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) { override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
itemView.sessionRow.setData(row as Session) val sessionRow = itemView.findViewById<SessionRowView>(R.id.sessionRow)
sessionRow.setData(row as Session)
val listener = View.OnClickListener { val listener = View.OnClickListener {
adapter.delegate?.onRowSelected(position, row) adapter.delegate?.onRowSelected(position, row)
} }
itemView.sessionRow.setOnClickListener(listener) sessionRow.setOnClickListener(listener)
} }
} }
@ -449,11 +449,13 @@ enum class RowViewType(private var layoutRes: Int) : ViewIdentifier {
inner class RowTransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), inner class RowTransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder { BindableHolder {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) { override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
itemView.transactionRow.setData(row as Transaction) val transactionRow = itemView.findViewById<TransactionRowView>(R.id.transactionRow)
transactionRow.setData(row as Transaction)
val listener = View.OnClickListener { val listener = View.OnClickListener {
adapter.delegate?.onRowSelected(position, row) adapter.delegate?.onRowSelected(position, row)
} }
itemView.transactionRow.setOnClickListener(listener) transactionRow.setOnClickListener(listener)
} }
} }

@ -4,9 +4,10 @@ import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isVisible import androidx.core.view.isVisible
import kotlinx.android.synthetic.main.row_session_view.view.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.ComputedStat import net.pokeranalytics.android.calculus.ComputedStat
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
@ -27,6 +28,19 @@ class SessionRowView : FrameLayout {
private lateinit var rowSession: ConstraintLayout private lateinit var rowSession: ConstraintLayout
private lateinit var dateDay: TextView
private lateinit var dateNumber: TextView
private lateinit var sessionTitle: TextView
private lateinit var sessionInfoDurationIcon: ImageView
private lateinit var sessionInfoDurationValue: TextView
private lateinit var sessionInfoLocationIcon: ImageView
private lateinit var sessionInfoLocationValue: TextView
private lateinit var sessionInfoTableIcon: ImageView
private lateinit var sessionInfoTableValue: TextView
private lateinit var gameResult: TextView
private lateinit var infoIcon: ImageView
private lateinit var infoTitle: TextView
/** /**
* Constructors * Constructors
*/ */
@ -48,8 +62,21 @@ class SessionRowView : FrameLayout {
private fun init() { private fun init() {
val layoutInflater = LayoutInflater.from(context) val layoutInflater = LayoutInflater.from(context)
rowSession = layoutInflater.inflate(R.layout.row_session_view, this, false) as ConstraintLayout rowSession = layoutInflater.inflate(R.layout.row_session_view, this, false) as ConstraintLayout
val layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT) val layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
addView(rowSession, layoutParams) addView(rowSession, layoutParams)
this.dateDay = rowSession.findViewById(R.id.dateDay)
this.dateNumber = rowSession.findViewById(R.id.dateNumber)
this.sessionTitle = rowSession.findViewById(R.id.sessionTitle)
this.sessionInfoDurationIcon = rowSession.findViewById(R.id.sessionInfoDurationIcon)
this.sessionInfoDurationValue = rowSession.findViewById(R.id.sessionInfoDurationValue)
this.sessionInfoLocationIcon = rowSession.findViewById(R.id.sessionInfoLocationIcon)
this.sessionInfoLocationValue = rowSession.findViewById(R.id.sessionInfoLocationValue)
this.sessionInfoTableIcon = rowSession.findViewById(R.id.sessionInfoTableIcon)
this.sessionInfoTableValue = sessionInfoTableValue.findViewById(R.id.dateDay)
this.gameResult = rowSession.findViewById(R.id.gameResult)
this.infoIcon = rowSession.findViewById(R.id.infoIcon)
this.infoTitle = rowSession.findViewById(R.id.infoTitle)
} }
/** /**
@ -60,69 +87,69 @@ class SessionRowView : FrameLayout {
val date = session.startDate ?: session.creationDate val date = session.startDate ?: session.creationDate
// Date // Date
rowSession.dateDay.text = date.getShortDayName() this.dateDay.text = date.getShortDayName()
rowSession.dateNumber.text = date.getDayNumber() this.dateNumber.text = date.getDayNumber()
// Title / Game type // Title / Game type
rowSession.sessionTitle.text = session.getFormattedGameType(context) this.sessionTitle.text = session.getFormattedGameType(context)
// Duration // Duration
rowSession.sessionInfoDurationValue.text = session.getFormattedDuration() this.sessionInfoDurationValue.text = session.getFormattedDuration()
// Location // Location
rowSession.sessionInfoLocationIcon.isVisible = session.location != null this.sessionInfoLocationIcon.isVisible = session.location != null
rowSession.sessionInfoLocationValue.isVisible = session.location != null this.sessionInfoLocationValue.isVisible = session.location != null
session.location?.let { session.location?.let {
rowSession.sessionInfoLocationValue.text = it.name this.sessionInfoLocationValue.text = it.name
} }
// Table size // Table size
rowSession.sessionInfoTableIcon.isVisible = session.tableSize != null this.sessionInfoTableIcon.isVisible = session.tableSize != null
rowSession.sessionInfoTableValue.isVisible = session.tableSize != null this.sessionInfoTableValue.isVisible = session.tableSize != null
session.tableSize?.let { session.tableSize?.let {
rowSession.sessionInfoTableValue.text = TableSize(it).localizedTitle(context) this.sessionInfoTableValue.text = TableSize(it).localizedTitle(context)
} }
val state = session.getState() val state = session.getState()
rowSession.sessionInfoDurationIcon.isVisible = state.hasStarted this.sessionInfoDurationIcon.isVisible = state.hasStarted
rowSession.sessionInfoDurationValue.isVisible = state.hasStarted this.sessionInfoDurationValue.isVisible = state.hasStarted
// State // State
when (state) { when (state) {
SessionState.STARTED -> { SessionState.STARTED -> {
rowSession.gameResult.isVisible = false this.gameResult.isVisible = false
rowSession.infoIcon.isVisible = true this.infoIcon.isVisible = true
rowSession.infoIcon.setImageResource(R.drawable.ic_play_circle_outline) this.infoIcon.setImageResource(R.drawable.ic_play_circle_outline)
rowSession.infoTitle.isVisible = true this.infoTitle.isVisible = true
rowSession.infoTitle.text = context.getString(R.string.running_session_state) this.infoTitle.text = context.getString(R.string.running_session_state)
} }
SessionState.PAUSED -> { SessionState.PAUSED -> {
rowSession.gameResult.isVisible = false this.gameResult.isVisible = false
rowSession.infoIcon.isVisible = true this.infoIcon.isVisible = true
rowSession.infoIcon.setImageResource(R.drawable.ic_pause_circle_outline) this.infoIcon.setImageResource(R.drawable.ic_pause_circle_outline)
rowSession.infoTitle.isVisible = true this.infoTitle.isVisible = true
rowSession.infoTitle.text = context.getString(R.string.paused_session_state) this.infoTitle.text = context.getString(R.string.paused_session_state)
} }
SessionState.PLANNED -> { SessionState.PLANNED -> {
rowSession.gameResult.isVisible = false this.gameResult.isVisible = false
rowSession.infoIcon.isVisible = true this.infoIcon.isVisible = true
rowSession.infoIcon.setImageResource(R.drawable.ic_planned) this.infoIcon.setImageResource(R.drawable.ic_planned)
rowSession.infoTitle.isVisible = true this.infoTitle.isVisible = true
rowSession.infoTitle.text = session.startDate!!.shortTime() this.infoTitle.text = session.startDate!!.shortTime()
} }
SessionState.PENDING -> { SessionState.PENDING -> {
rowSession.gameResult.isVisible = false this.gameResult.isVisible = false
rowSession.infoIcon.isVisible = false this.infoIcon.isVisible = false
rowSession.infoTitle.isVisible = false this.infoTitle.isVisible = false
} }
else -> { else -> {
rowSession.gameResult.isVisible = true this.gameResult.isVisible = true
rowSession.infoIcon.isVisible = false this.infoIcon.isVisible = false
rowSession.infoTitle.isVisible = false this.infoTitle.isVisible = false
session.result?.net?.let { netResult -> session.result?.net?.let { netResult ->
val stat = ComputedStat(Stat.NET_RESULT, netResult, currency = session.currency) val stat = ComputedStat(Stat.NET_RESULT, netResult, currency = session.currency)
rowSession.gameResult.setTextFormat(stat.textFormat, context) this.gameResult.setTextFormat(stat.textFormat, context)
} }
// val formattedStat = ComputedStat(Stat.NET_RESULT, result, currency = session.currency).format() // val formattedStat = ComputedStat(Stat.NET_RESULT, result, currency = session.currency).format()

@ -4,8 +4,8 @@ import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import kotlinx.android.synthetic.main.row_transaction_view.view.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.ComputedStat import net.pokeranalytics.android.calculus.ComputedStat
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
@ -52,21 +52,21 @@ class TransactionRowView : FrameLayout {
fun setData(transaction: Transaction) { fun setData(transaction: Transaction) {
// Date // Date
rowTransaction.transactionDateDay.text = transaction.date.getShortDayName() rowTransaction.findViewById<TextView>(R.id.transactionDateDay).text = transaction.date.getShortDayName()
rowTransaction.transactionDateNumber.text = transaction.date.getDayNumber() rowTransaction.findViewById<TextView>(R.id.transactionDateNumber).text = transaction.date.getDayNumber()
// Title / Game type // Title / Game type
val title = transaction.type?.name ?: "" + " " + transaction.comment val title = transaction.type?.name ?: "" + " " + transaction.comment
val subtitle = transaction.bankroll?.name val subtitle = transaction.bankroll?.name
rowTransaction.transactionTitle.text = title rowTransaction.findViewById<TextView>(R.id.transactionTitle).text = title
rowTransaction.transactionSubtitle.text = subtitle rowTransaction.findViewById<TextView>(R.id.transactionSubtitle).text = subtitle
// Amount // Amount
val computedStat = ComputedStat(Stat.NET_RESULT, val computedStat = ComputedStat(Stat.NET_RESULT,
transaction.amount, transaction.amount,
currency = transaction.bankroll?.utilCurrency) currency = transaction.bankroll?.utilCurrency)
rowTransaction.transactionAmount.setTextFormat(computedStat.textFormat, context) rowTransaction.findViewById<TextView>(R.id.transactionAmount).setTextFormat(computedStat.textFormat, context)
} }

@ -4,10 +4,10 @@ import android.content.Context
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import com.github.mikephil.charting.data.BarDataSet import com.github.mikephil.charting.data.BarDataSet
import com.github.mikephil.charting.data.LineDataSet import com.github.mikephil.charting.data.LineDataSet
import net.pokeranalytics.android.calculus.AxisFormatting
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.ui.fragment.GraphFragment import net.pokeranalytics.android.ui.graph.Graph
import net.pokeranalytics.android.ui.graph.AxisFormatting
open class GraphViewModel : ViewModel(), GraphDataProvider { open class GraphViewModel : ViewModel(), GraphDataProvider {
@ -19,7 +19,7 @@ open class GraphViewModel : ViewModel(), GraphDataProvider {
/*** /***
* The graph style * The graph style
*/ */
var style: GraphFragment.Style? = null var style: Graph.Style? = null
/*** /***
* The displayed stat * The displayed stat

@ -3,10 +3,9 @@ package net.pokeranalytics.android.ui.viewmodel
import android.content.Context import android.content.Context
import com.github.mikephil.charting.data.BarDataSet import com.github.mikephil.charting.data.BarDataSet
import com.github.mikephil.charting.data.LineDataSet import com.github.mikephil.charting.data.LineDataSet
import net.pokeranalytics.android.calculus.AxisFormatting
import net.pokeranalytics.android.calculus.Report import net.pokeranalytics.android.calculus.Report
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.ui.fragment.GraphFragment
import net.pokeranalytics.android.ui.graph.AxisFormatting
interface ReportHolder { interface ReportHolder {

@ -3,6 +3,9 @@ package net.pokeranalytics.android.ui.viewmodel
import android.content.Context import android.content.Context
import com.github.mikephil.charting.data.BarDataSet import com.github.mikephil.charting.data.BarDataSet
import com.github.mikephil.charting.data.LineDataSet import com.github.mikephil.charting.data.LineDataSet
import net.pokeranalytics.android.calcul.barEntries
import net.pokeranalytics.android.calcul.lineEntries
import net.pokeranalytics.android.calcul.multiLineEntries
import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.Calculator
import net.pokeranalytics.android.calculus.Report import net.pokeranalytics.android.calculus.Report
import net.pokeranalytics.android.ui.activity.components.ReportParameters import net.pokeranalytics.android.ui.activity.components.ReportParameters
@ -15,7 +18,7 @@ class ReportViewModel : GraphViewModel(), ReportHolder, GraphDataProvider {
companion object { companion object {
// Unparcel fails when setting a custom Parcelable object on Entry so we use a static reference to passe objects // Unparcel fails when setting a custom Parcelable object on Entry so we use a static reference to pass objects
private var _parameters: ReportParameters? = null private var _parameters: ReportParameters? = null
val parameters: ReportParameters? val parameters: ReportParameters?

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

@ -1,13 +1,13 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.4.10' ext.kotlin_version = '1.4.21'
repositories { repositories {
google() google()
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.0.2' classpath 'com.android.tools.build:gradle:4.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'io.realm:realm-gradle-plugin:5.15.2' classpath 'io.realm:realm-gradle-plugin:5.15.2'

@ -35,4 +35,6 @@ android.enableBuildCache=true
# Enable simple gradle caching # Enable simple gradle caching
org.gradle.caching=true org.gradle.caching=true
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false

@ -1,6 +1,6 @@
#Mon Oct 05 18:40:01 CEST 2020 #Wed Dec 09 14:45:29 CET 2020
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip

@ -1 +1,2 @@
include ':shared'
include ':app' include ':app'

@ -0,0 +1,42 @@
plugins {
kotlin("multiplatform")
id("com.android.library")
}
kotlin {
android()
ios {
binaries {
framework {
baseName = "shared"
}
}
}
sourceSets {
val commonMain by getting
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val androidMain by getting
val androidTest by getting {
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:4.13")
}
}
val iosMain by getting
val iosTest by getting
}
}
android {
compileSdkVersion(29)
defaultConfig {
minSdkVersion(24)
targetSdkVersion(29)
}
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
}

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="net.pokeranalytics.shared" />

@ -0,0 +1,5 @@
package net.pokeranalytics.shared
actual class Platform actual constructor() {
actual val platform: String = "Android ${android.os.Build.VERSION.SDK_INT}"
}

@ -0,0 +1,12 @@
package net.pokeranalytics.shared
import org.junit.Assert.assertTrue
import org.junit.Test
class GreetingTest {
@Test
fun testExample() {
assertTrue("Check Android is mentioned", Greeting().greeting().contains("Android"))
}
}

@ -0,0 +1,7 @@
package net.pokeranalytics.shared
class Greeting {
fun greeting(): String {
return "Hello, ${Platform().platform}!"
}
}

@ -0,0 +1,5 @@
package net.pokeranalytics.shared
expect class Platform() {
val platform: String
}

@ -0,0 +1,8 @@
package net.pokeranalytics.shared
import platform.UIKit.UIDevice
actual class Platform actual constructor() {
actual val platform: String =
UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion
}

@ -0,0 +1,12 @@
package net.pokeranalytics.shared
import kotlin.test.Test
import kotlin.test.assertTrue
class GreetingTest {
@Test
fun testExample() {
assertTrue(Greeting().greeting().contains("iOS"), "Check iOS is mentioned")
}
}
Loading…
Cancel
Save