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

feature/top10
Laurent 7 years ago
commit cfcd4eeeda
  1. 2
      .gitlab-ci.yml
  2. 9
      app/build.gradle
  3. 29
      app/src/main/java/net/pokeranalytics/android/model/LiveData.kt
  4. 23
      app/src/main/java/net/pokeranalytics/android/model/filter/FilterComponent.kt
  5. 14
      app/src/main/java/net/pokeranalytics/android/model/filter/Filterable.kt
  6. 20
      app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt
  7. 5
      app/src/main/java/net/pokeranalytics/android/model/realm/Game.kt
  8. 22
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  9. 4
      app/src/main/java/net/pokeranalytics/android/model/realm/TournamentFeature.kt
  10. 3
      app/src/main/java/net/pokeranalytics/android/model/realm/TournamentName.kt
  11. 54
      app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt
  12. 10
      app/src/main/java/net/pokeranalytics/android/ui/activity/CurrenciesActivity.kt
  13. 4
      app/src/main/java/net/pokeranalytics/android/ui/activity/EditableDataActivity.kt
  14. 190
      app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollDataFragment.kt
  15. 15
      app/src/main/java/net/pokeranalytics/android/ui/fragment/CurrenciesFragment.kt
  16. 3
      app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt
  17. 4
      app/src/main/java/net/pokeranalytics/android/ui/fragment/HistoryFragment.kt
  18. 22
      app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt
  19. 89
      app/src/main/java/net/pokeranalytics/android/ui/fragment/TransactionDataFragment.kt
  20. 8
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt
  21. 31
      app/src/main/java/net/pokeranalytics/android/ui/helpers/DateTimePickerManager.kt
  22. 19
      app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt
  23. 71
      app/src/main/java/net/pokeranalytics/android/ui/view/TransactionRowView.kt
  24. 28
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/BankrollRow.kt
  25. 32
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SessionRow.kt
  26. 4
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt
  27. 86
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/TransactionRow.kt
  28. 12
      app/src/main/res/layout/row_transaction.xml
  29. 108
      app/src/main/res/layout/row_transaction_view.xml
  30. 11
      app/src/test/java/net/pokeranalytics/android/RealmUnitTest.kt

@ -38,7 +38,7 @@ assembleDebug:
paths: paths:
- app/build/outputs/ - app/build/outputs/
#debugTests: unitTests:
stage: test stage: test
script: script:
- ./gradlew -Pci --console=plain :app:testDebug - ./gradlew -Pci --console=plain :app:testDebug

@ -75,13 +75,10 @@ dependencies {
implementation 'com.jakewharton.timber:timber:4.7.1' implementation 'com.jakewharton.timber:timber:4.7.1'
// Test // Test
androidTestImplementation 'androidx.test:core:1.0.0'
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test:rules:1.1.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
// Required -- JUnit 4 framework
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
testImplementation "org.mockito:mockito-core:1.10.19"
testImplementation "org.robolectric:robolectric:4.2"
testImplementation 'io.reactivex.rxjava2:rxjava:2.1.13'
testImplementation "org.powermock:powermock-module-junit4:1.6.6" testImplementation "org.powermock:powermock-module-junit4:1.6.6"
testImplementation "org.powermock:powermock-module-junit4-rule:1.6.6" testImplementation "org.powermock:powermock-module-junit4-rule:1.6.6"

@ -9,10 +9,8 @@ import io.realm.kotlin.where
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.interfaces.CountableUsage import net.pokeranalytics.android.model.interfaces.CountableUsage
import net.pokeranalytics.android.model.interfaces.Manageable import net.pokeranalytics.android.model.interfaces.Manageable
import net.pokeranalytics.android.model.interfaces.Timed
import net.pokeranalytics.android.model.realm.* import net.pokeranalytics.android.model.realm.*
import net.pokeranalytics.android.ui.view.Localizable import net.pokeranalytics.android.ui.view.Localizable
import timber.log.Timber
/** /**
* An enum managing the business objects related to a realm results * An enum managing the business objects related to a realm results
@ -23,6 +21,7 @@ enum class LiveData : Localizable {
LOCATION, LOCATION,
TOURNAMENT_NAME, TOURNAMENT_NAME,
TOURNAMENT_FEATURE, TOURNAMENT_FEATURE,
TRANSACTION,
TRANSACTION_TYPE; TRANSACTION_TYPE;
fun items(realm: Realm, fieldName: String? = null, sortOrder: Sort? = null): RealmResults<*> { fun items(realm: Realm, fieldName: String? = null, sortOrder: Sort? = null): RealmResults<*> {
@ -76,9 +75,21 @@ enum class LiveData : Localizable {
return results return results
} }
private var sortingFieldName: String = "name" private val sortingFieldName: String
private var sorting: Sort = Sort.ASCENDING get() {
return when (this) {
TRANSACTION -> "date"
else -> "name"
}
}
private val sorting: Sort
get() {
return when (this) {
TRANSACTION -> Sort.DESCENDING
else -> Sort.ASCENDING
}
}
private val relatedEntity: Class<out RealmObject> private val relatedEntity: Class<out RealmObject>
get() { get() {
@ -88,6 +99,7 @@ enum class LiveData : Localizable {
LOCATION -> Location::class.java LOCATION -> Location::class.java
TOURNAMENT_NAME -> TournamentName::class.java TOURNAMENT_NAME -> TournamentName::class.java
TOURNAMENT_FEATURE -> TournamentFeature::class.java TOURNAMENT_FEATURE -> TournamentFeature::class.java
TRANSACTION -> Transaction::class.java
TRANSACTION_TYPE -> TransactionType::class.java TRANSACTION_TYPE -> TransactionType::class.java
} }
} }
@ -128,6 +140,7 @@ enum class LiveData : Localizable {
LOCATION -> R.string.location LOCATION -> R.string.location
TOURNAMENT_NAME -> R.string.tournament_name TOURNAMENT_NAME -> R.string.tournament_name
TOURNAMENT_FEATURE -> R.string.tournament_feature TOURNAMENT_FEATURE -> R.string.tournament_feature
TRANSACTION -> R.string.operations
TRANSACTION_TYPE -> R.string.operation_types TRANSACTION_TYPE -> R.string.operation_types
} }
} }
@ -135,13 +148,5 @@ enum class LiveData : Localizable {
fun newEntityLocalizedTitle(context: Context): String { fun newEntityLocalizedTitle(context: Context): String {
return "${context.getString(R.string.new_entity)} ${this.localizedTitle(context)}" return "${context.getString(R.string.new_entity)} ${this.localizedTitle(context)}"
} }
}
/*
interface ListableDataSource {
fun items(realm: Realm, fieldName: String? = null, sortOrder: Sort? = null): RealmResults<*>
var sortingFieldName: String
var sorting: Sort
var relatedEntity: Class < out RealmObject >
} }
*/

@ -1,5 +1,28 @@
package net.pokeranalytics.android.model.filter package net.pokeranalytics.android.model.filter
import io.realm.Realm
import io.realm.RealmObject
import io.realm.RealmQuery
import io.realm.RealmResults
import net.pokeranalytics.android.model.realm.Session
enum class FilterComponent { enum class FilterComponent {
} }
enum class SessionFilterable(var fieldName:String? = null) : Filterable {
LIVE("bankroll.live"),
CASH("type"),
ONLINE,
TOURNAMENT
;
override fun filter(realmQuery: RealmQuery<*>): RealmQuery<out RealmObject> {
return when (this) {
LIVE -> realmQuery.equalTo(this.fieldName, true) as RealmQuery<out RealmObject>
CASH -> realmQuery.equalTo(this.fieldName, Session.Type.CASH_GAME.ordinal) as RealmQuery<out RealmObject>
ONLINE -> LIVE.filter(realmQuery.not())
TOURNAMENT -> CASH.filter(realmQuery.not())
}
}
}

@ -1,7 +1,11 @@
package net.pokeranalytics.android.model.filter package net.pokeranalytics.android.model.filter
import io.realm.Realm
import io.realm.RealmObject import io.realm.RealmObject
import io.realm.RealmQuery
import io.realm.RealmResults import io.realm.RealmResults
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.realm.*
/** /**
* We want to be able to store filters in the database: * We want to be able to store filters in the database:
@ -30,7 +34,7 @@ import io.realm.RealmResults
*/ */
interface Filterable { interface Filterable {
fun filter(realmQuery: RealmQuery<*>): RealmQuery<out RealmObject>
} }
class FilterManager { class FilterManager {
@ -38,6 +42,14 @@ class FilterManager {
fun test(realmResults: RealmResults<RealmObject>) { fun test(realmResults: RealmResults<RealmObject>) {
realmResults.where().greaterThan("test", 5).findAll() realmResults.where().greaterThan("test", 5).findAll()
} }
fun filter(realm:Realm, relatedEntity: Class<out RealmObject>, queries:List<Filterable>): RealmResults<*> {
var realmQuery = realm.where(relatedEntity)
queries.forEach {
realmQuery = it.filter(realmQuery).and()
}
return realmQuery.findAll()
}
} }
// //
//fun MutableList<Filterable>.filter(filter: FilterComponent) : List<Filterable> { //fun MutableList<Filterable>.filter(filter: FilterComponent) : List<Filterable> {

@ -9,24 +9,28 @@ import net.pokeranalytics.android.model.interfaces.Manageable
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
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.rowrepresentable.BankrollRow import net.pokeranalytics.android.ui.view.rowrepresentable.BankrollRow
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow
import net.pokeranalytics.android.util.NULL_TEXT
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
open class Bankroll(name: String = "") : RealmObject(), Manageable, open class Bankroll(name: String = "") : RealmObject(), Manageable, StaticRowRepresentableDataSource, RowRepresentable {
StaticRowRepresentableDataSource, RowRepresentable {
companion object { companion object {
fun newInstance() : Bankroll { fun newInstance() : Bankroll {
var bankroll: Bankroll = Bankroll() val bankroll = Bankroll()
return bankroll return bankroll
} }
val rowRepresentation : List<RowRepresentable> by lazy { val rowRepresentation : List<RowRepresentable> by lazy {
val rows = ArrayList<RowRepresentable>() val rows = ArrayList<RowRepresentable>()
rows.add(SimpleRow.NAME) rows.add(SimpleRow.NAME)
rows.addAll(BankrollRow.values()) rows.add(BankrollRow.LIVE)
rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.currency))
rows.add(BankrollRow.CURRENCY)
rows rows
} }
} }
@ -57,7 +61,7 @@ open class Bankroll(name: String = "") : RealmObject(), Manageable,
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(row: RowRepresentable): String {
return when (row) { return when (row) {
SimpleRow.NAME -> this.name SimpleRow.NAME -> if (this.name.isNotEmpty()) this.name else NULL_TEXT
else -> return super.stringForRow(row) else -> return super.stringForRow(row)
} }
} }
@ -79,6 +83,12 @@ open class Bankroll(name: String = "") : RealmObject(), Manageable,
BankrollRow.LIVE -> { BankrollRow.LIVE -> {
this.live = if (value is Boolean) !value else false this.live = if (value is Boolean) !value else false
} }
BankrollRow.CURRENCY -> {
this.currency?.code = value as String?
}
BankrollRow.RATE -> {
this.currency?.rate = (value as String? ?: "0").toDouble()
}
} }
} }

@ -10,6 +10,7 @@ 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.GameRow import net.pokeranalytics.android.ui.view.rowrepresentable.GameRow
import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow
import net.pokeranalytics.android.util.NULL_TEXT
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
@ -46,8 +47,8 @@ open class Game : RealmObject(), Manageable, StaticRowRepresentableDataSource, R
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(row: RowRepresentable): String {
return when (row) { return when (row) {
SimpleRow.NAME -> this.name SimpleRow.NAME -> if (this.name.isNotEmpty()) this.name else NULL_TEXT
GameRow.SHORT_NAME -> this.shortName ?: "" GameRow.SHORT_NAME -> this.shortName ?: NULL_TEXT
else -> return super.stringForRow(row) else -> return super.stringForRow(row)
} }
} }

@ -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 android.text.InputType
import io.realm.Realm import io.realm.Realm
import io.realm.RealmList import io.realm.RealmList
import io.realm.RealmObject import io.realm.RealmObject
@ -166,6 +165,7 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource
var cgBigBlind: Double? = null var cgBigBlind: Double? = null
set(value) { set(value) {
this.hasBigBlind = if (value != null) 1 else 0 this.hasBigBlind = if (value != null) 1 else 0
field = value
} }
// Tournament // Tournament
@ -412,7 +412,7 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource
/** /**
* Return the formatted blinds * Return the formatted blinds
*/ */
fun getBlinds(): String { fun getBlinds(): String {
val currencyCode = bankroll?.currency?.code ?: Currency.getInstance(Locale.getDefault()).currencyCode val currencyCode = bankroll?.currency?.code ?: Currency.getInstance(Locale.getDefault()).currencyCode
val currencySymbol = Currency.getInstance(currencyCode).symbol val currencySymbol = Currency.getInstance(currencyCode).symbol
return if (cgSmallBlind == null) NULL_TEXT else "$currencySymbol ${cgSmallBlind?.formatted()}/${cgBigBlind?.round()}" return if (cgSmallBlind == null) NULL_TEXT else "$currencySymbol ${cgSmallBlind?.formatted()}/${cgBigBlind?.round()}"
@ -618,30 +618,30 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource
SessionRow.TABLE_SIZE -> row.editingDescriptors(mapOf( SessionRow.TABLE_SIZE -> row.editingDescriptors(mapOf(
"defaultValue" to this.tableSize)) "defaultValue" to this.tableSize))
SessionRow.BLINDS -> row.editingDescriptors(mapOf( SessionRow.BLINDS -> row.editingDescriptors(mapOf(
"SB" to cgSmallBlind?.round(), "sb" to cgSmallBlind?.round(),
"BB" to cgBigBlind?.round() "bb" to cgBigBlind?.round()
)) ))
SessionRow.BUY_IN -> row.editingDescriptors(mapOf( SessionRow.BUY_IN -> row.editingDescriptors(mapOf(
"BB" to cgBigBlind, "bb" to cgBigBlind,
"fee" to this.tournamentEntryFee, "fee" to this.tournamentEntryFee,
"buying" to buyin "buyin" to buyin
)) ))
SessionRow.BREAK_TIME -> row.editingDescriptors(mapOf()) SessionRow.BREAK_TIME -> row.editingDescriptors(mapOf())
SessionRow.CASHED_OUT, SessionRow.PRIZE, SessionRow.NET_RESULT -> row.editingDescriptors(mapOf( SessionRow.CASHED_OUT, SessionRow.PRIZE, SessionRow.NET_RESULT -> row.editingDescriptors(mapOf(
"result" to result?.cashout?.round() "defaultValue" to result?.cashout?.round()
)) ))
SessionRow.COMMENT -> row.editingDescriptors(mapOf( SessionRow.COMMENT -> row.editingDescriptors(mapOf(
"defaultValue" to this.comment)) "defaultValue" to this.comment))
SessionRow.INITIAL_BUY_IN -> row.editingDescriptors(mapOf( SessionRow.INITIAL_BUY_IN -> row.editingDescriptors(mapOf(
"fee" to this.tournamentEntryFee "defaultValue" to this.tournamentEntryFee
)) ))
SessionRow.PLAYERS -> row.editingDescriptors(mapOf( SessionRow.PLAYERS -> row.editingDescriptors(mapOf(
"defaultValue" to this.tournamentNumberOfPlayers)) "defaultValue" to this.tournamentNumberOfPlayers))
SessionRow.POSITION -> row.editingDescriptors(mapOf( SessionRow.POSITION -> row.editingDescriptors(mapOf(
"defaultValue" to this.result?.tournamentFinalPosition)) "defaultValue" to this.result?.tournamentFinalPosition))
SessionRow.TIPS -> row.editingDescriptors(mapOf( SessionRow.TIPS -> row.editingDescriptors(mapOf(
"SB" to cgSmallBlind?.round(), "sb" to cgSmallBlind?.round(),
"BB" to cgBigBlind?.round(), "bb" to cgBigBlind?.round(),
"tips" to result?.tips "tips" to result?.tips
)) ))
else -> null else -> null
@ -653,12 +653,12 @@ open class Session : RealmObject(), Manageable, StaticRowRepresentableDataSource
when (row) { when (row) {
SessionRow.BANKROLL -> bankroll = value as Bankroll? SessionRow.BANKROLL -> bankroll = value as Bankroll?
SessionRow.BLINDS -> if (value is ArrayList<*>) { SessionRow.BLINDS -> if (value is ArrayList<*>) {
cgSmallBlind = try { cgSmallBlind = try {
(value[0] as String? ?: "0").toDouble() (value[0] as String? ?: "0").toDouble()
} catch (e: Exception) { } catch (e: Exception) {
null null
} }
cgBigBlind = try { cgBigBlind = try {
(value[1] as String? ?: "0").toDouble() (value[1] as String? ?: "0").toDouble()
} catch (e: Exception) { } catch (e: Exception) {

@ -1,6 +1,5 @@
package net.pokeranalytics.android.model.realm package net.pokeranalytics.android.model.realm
import android.text.InputType
import io.realm.RealmObject import io.realm.RealmObject
import io.realm.annotations.PrimaryKey import io.realm.annotations.PrimaryKey
import net.pokeranalytics.android.model.interfaces.CountableUsage import net.pokeranalytics.android.model.interfaces.CountableUsage
@ -10,6 +9,7 @@ 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.SimpleRow import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow
import net.pokeranalytics.android.ui.view.rowrepresentable.TournamentFeatureRow import net.pokeranalytics.android.ui.view.rowrepresentable.TournamentFeatureRow
import net.pokeranalytics.android.util.NULL_TEXT
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
@ -44,7 +44,7 @@ open class TournamentFeature : RealmObject(), Manageable, StaticRowRepresentable
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(row: RowRepresentable): String {
return when (row) { return when (row) {
SimpleRow.NAME -> this.name SimpleRow.NAME -> if (this.name.isNotEmpty()) this.name else NULL_TEXT
else -> return super.stringForRow(row) else -> return super.stringForRow(row)
} }
} }

@ -9,6 +9,7 @@ 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.SimpleRow import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow
import net.pokeranalytics.android.ui.view.rowrepresentable.TournamentNameRow import net.pokeranalytics.android.ui.view.rowrepresentable.TournamentNameRow
import net.pokeranalytics.android.util.NULL_TEXT
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
@ -45,7 +46,7 @@ open class TournamentName : RealmObject(), Manageable, StaticRowRepresentableDat
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(row: RowRepresentable): String {
return when (row) { return when (row) {
SimpleRow.NAME -> this.name SimpleRow.NAME -> if (this.name.isNotEmpty()) this.name else NULL_TEXT
else -> return super.stringForRow(row) else -> return super.stringForRow(row)
} }
} }

@ -1,14 +1,33 @@
package net.pokeranalytics.android.model.realm package net.pokeranalytics.android.model.realm
import io.realm.RealmObject import io.realm.RealmObject
import io.realm.annotations.Ignore
import io.realm.annotations.PrimaryKey import io.realm.annotations.PrimaryKey
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.interfaces.Manageable
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.rowrepresentable.TransactionRow
import java.util.* import java.util.*
import kotlin.collections.ArrayList
open class Transaction : RealmObject() { open class Transaction : RealmObject(), Manageable, StaticRowRepresentableDataSource, RowRepresentable {
companion object {
val rowRepresentation : List<RowRepresentable> by lazy {
val rows = ArrayList<RowRepresentable>()
rows.addAll(TransactionRow.values())
rows
}
}
@PrimaryKey @PrimaryKey
var id = UUID.randomUUID().toString() override var id = UUID.randomUUID().toString()
// The bankroll of the transaction
var bankroll: Bankroll? = null
// The amount of the transaction // The amount of the transaction
var amount: Double = 0.0 var amount: Double = 0.0
@ -22,5 +41,36 @@ open class Transaction : RealmObject() {
// A user comment // A user comment
var comment: String = "" var comment: String = ""
@Ignore
override val viewType: Int = RowViewType.ROW_TRANSACTION.ordinal
override fun updateValue(value: Any?, row: RowRepresentable) {
when(row) {
TransactionRow.BANKROLL -> bankroll = value as Bankroll?
TransactionRow.TYPE -> type = value as TransactionType?
TransactionRow.AMOUNT -> amount = if (value == null) 0.0 else (value as String).toDouble()
TransactionRow.COMMENT -> comment = value as String? ?: ""
TransactionRow.DATE -> date = value as Date? ?: Date()
}
}
override fun adapterRows(): List<RowRepresentable>? {
return rowRepresentation
}
override fun isValidForSave(): Boolean {
return bankroll != null && type != null && amount != 0.0
}
override fun getFailedSaveMessage(): Int {
return if (bankroll == null) {
R.string.no_br_popup_message
} else if (type == null || amount == 0.0) {
R.string.operation_empty_field_error
} else {
super.getFailedSaveMessage()
}
}
} }

@ -3,6 +3,7 @@ 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 androidx.fragment.app.Fragment
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
@ -13,6 +14,15 @@ class CurrenciesActivity : PokerAnalyticsActivity() {
val intent = Intent(context, CurrenciesActivity::class.java) val intent = Intent(context, CurrenciesActivity::class.java)
context.startActivity(intent) context.startActivity(intent)
} }
/**
* Create a new instance for result
*/
fun newInstanceForResult(fragment: Fragment, requestCode: Int) {
val intent = Intent(fragment.requireContext(), CurrenciesActivity::class.java)
fragment.startActivityForResult(intent, requestCode)
}
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {

@ -7,8 +7,10 @@ import androidx.fragment.app.Fragment
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.fragment.BankrollDataFragment
import net.pokeranalytics.android.ui.fragment.EditableDataFragment import net.pokeranalytics.android.ui.fragment.EditableDataFragment
import net.pokeranalytics.android.ui.fragment.LocationDataFragment import net.pokeranalytics.android.ui.fragment.LocationDataFragment
import net.pokeranalytics.android.ui.fragment.TransactionDataFragment
class EditableDataActivity : PokerAnalyticsActivity() { class EditableDataActivity : PokerAnalyticsActivity() {
enum class IntentKey(val keyName: String) { enum class IntentKey(val keyName: String) {
@ -60,7 +62,9 @@ class EditableDataActivity : PokerAnalyticsActivity() {
val fragmentManager = supportFragmentManager val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction() val fragmentTransaction = fragmentManager.beginTransaction()
val fragment: EditableDataFragment = when (dataType) { val fragment: EditableDataFragment = when (dataType) {
LiveData.BANKROLL.ordinal -> BankrollDataFragment()
LiveData.LOCATION.ordinal -> LocationDataFragment() LiveData.LOCATION.ordinal -> LocationDataFragment()
LiveData.TRANSACTION.ordinal -> TransactionDataFragment()
else -> EditableDataFragment() else -> EditableDataFragment()
} }

@ -0,0 +1,190 @@
package net.pokeranalytics.android.ui.fragment
import android.app.Activity.RESULT_OK
import android.content.Intent
import android.os.Bundle
import android.view.View
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.Bankroll
import net.pokeranalytics.android.ui.activity.CurrenciesActivity
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.rowrepresentable.BankrollRow
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow
import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.Preferences
import net.pokeranalytics.android.util.extensions.round
import java.util.*
/**
* Custom EditableDataFragment to manage the Bankroll data
*/
class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataSource {
companion object {
const val REQUEST_CODE_CURRENCY: Int = 100
}
// Return the item as a Bankroll object
private val bankroll: Bankroll
get() {
return this.item as Bankroll
}
private lateinit var defaultCurrency: Currency
private val rows = ArrayList<RowRepresentable>()
private var isRefreshingRate = false
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
shouldOpenKeyboard = false
initData()
refreshRows()
updateAdapterUI()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE_CURRENCY && resultCode == RESULT_OK) {
data?.let {
val currencyCode = it.getStringExtra(CurrenciesFragment.INTENT_CURRENCY_CODE)
onRowValueChanged(currencyCode, BankrollRow.CURRENCY)
}
}
}
override fun getDataSource(): RowRepresentableDataSource {
return this
}
override fun adapterRows(): List<RowRepresentable>? {
return rows
}
override fun stringForRow(row: RowRepresentable): String {
return when (row) {
SimpleRow.NAME -> if (bankroll.name.isNotEmpty()) bankroll.name else NULL_TEXT
BankrollRow.CURRENCY -> {
bankroll.currency?.let {
Currency.getInstance(it.code).currencyCode
} ?: run {
NULL_TEXT
}
}
BankrollRow.RATE -> {
bankroll.currency?.let {
(it.rate ?: 1.0).round()
} ?: run {
1.0.round()
}
}
else -> super.stringForRow(row)
}
}
override fun boolForRow(row: RowRepresentable): Boolean {
return when(row) {
BankrollRow.LIVE -> !bankroll.live
BankrollRow.REFRESH_RATE -> isRefreshingRate
else -> super.boolForRow(row)
}
}
override fun editDescriptors(row: RowRepresentable): ArrayList<RowRepresentableEditDescriptor>? {
return when (row) {
SimpleRow.NAME -> row.editingDescriptors(mapOf("defaultValue" to this.bankroll.name))
BankrollRow.RATE -> row.editingDescriptors(mapOf("defaultValue" to (this.bankroll.currency?.rate ?: 1.0).round()))
else -> null
}
}
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
when (row) {
BankrollRow.CURRENCY -> CurrenciesActivity.newInstanceForResult(this@BankrollDataFragment, BankrollDataFragment.REQUEST_CODE_CURRENCY)
BankrollRow.REFRESH_RATE -> {
isRefreshingRate = true
//TODO: Call web-service to get the currency rate
GlobalScope.launch(Dispatchers.Main) {
delay(1500)
isRefreshingRate = false
rowRepresentableAdapter.refreshRow(BankrollRow.REFRESH_RATE)
}
rowRepresentableAdapter.refreshRow(BankrollRow.REFRESH_RATE)
}
else -> super.onRowSelected(position, row, fromAction)
}
}
override fun onRowValueChanged(value: Any?, row: RowRepresentable) {
super.onRowValueChanged(value, row)
updateAdapterUI()
}
/**
* Init data
*/
private fun initData() {
defaultCurrency = Currency.getInstance(Preferences.getCurrencyLocale(this.parentActivity))
if (!isUpdating) {
bankroll.currency = net.pokeranalytics.android.model.realm.Currency()
bankroll.currency?.code = defaultCurrency.currencyCode
bankroll.currency?.rate = 1.0
}
}
/**
* Refresh rows
*/
private fun refreshRows() {
rows.clear()
rows.add(SimpleRow.NAME)
rows.add(BankrollRow.LIVE)
rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.currency))
rows.add(BankrollRow.CURRENCY)
val defaultCurrency = Currency.getInstance(Preferences.getCurrencyLocale(this.parentActivity))
var differentCurrency = false
bankroll.currency?.let { bankrollCurrency ->
differentCurrency = bankrollCurrency.code != defaultCurrency.currencyCode
}
if (differentCurrency) {
rows.add(BankrollRow.RATE)
rows.add(BankrollRow.REFRESH_RATE)
}
}
/**
* Update UI adapter
*/
private fun updateAdapterUI() {
val currentRowsSize = rows.size
refreshRows()
val newRowsSize = rows.size
if (currentRowsSize < newRowsSize) {
rowRepresentableAdapter.notifyItemRangeInserted(currentRowsSize, newRowsSize - currentRowsSize)
} else {
rowRepresentableAdapter.notifyItemRangeRemoved(newRowsSize, currentRowsSize - newRowsSize)
}
}
}

@ -1,6 +1,7 @@
package net.pokeranalytics.android.ui.fragment package net.pokeranalytics.android.ui.fragment
import android.app.Activity import android.app.Activity
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -16,12 +17,14 @@ import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
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.ui.view.rowrepresentable.SeparatorRowRepresentable import net.pokeranalytics.android.ui.view.rowrepresentable.SeparatorRowRepresentable
import net.pokeranalytics.android.util.Preferences
import java.util.* import java.util.*
class CurrenciesFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { class CurrenciesFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate {
companion object { companion object {
const val INTENT_CURRENCY_CODE = "INTENT_CURRENCY_CODE"
val rowRepresentation : List<RowRepresentable> by lazy { val rowRepresentation : List<RowRepresentable> by lazy {
val rows = ArrayList<RowRepresentable>() val rows = ArrayList<RowRepresentable>()
rows.addAll(mostUsedCurrencies) rows.addAll(mostUsedCurrencies)
@ -30,9 +33,8 @@ class CurrenciesFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataS
rows rows
} }
val mostUsedCurrencyCodes = arrayListOf("EUR", "USD", "CAD", "GBP", "AUD", "CNY") private val mostUsedCurrencyCodes = arrayListOf("EUR", "USD", "CAD", "GBP", "AUD", "CNY")
val systemCurrencies = Currency.getAvailableCurrencies() private val systemCurrencies = Currency.getAvailableCurrencies()
private val mostUsedCurrencies = this.mostUsedCurrencyCodes.map { code -> private val mostUsedCurrencies = this.mostUsedCurrencyCodes.map { code ->
CurrencyRow( CurrencyRow(
@ -89,8 +91,9 @@ class CurrenciesFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataS
// RowRepresentableDelegate // RowRepresentableDelegate
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
Preferences.setCurrencyCode((row as CurrencyRow).currency.currencyCode, this.context!!) val intent = Intent()
this.activity?.setResult(Activity.RESULT_OK) intent.putExtra(INTENT_CURRENCY_CODE, (row as CurrencyRow).currency.currencyCode)
this.activity?.setResult(Activity.RESULT_OK, intent)
this.activity?.finish() this.activity?.finish()
} }

@ -58,7 +58,8 @@ class DataListFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSourc
} }
override fun viewTypeForPosition(position: Int): Int { override fun viewTypeForPosition(position: Int): Int {
return RowViewType.DATA.ordinal val viewType = (this.items[position] as RowRepresentable).viewType
return if (viewType != -1) viewType else RowViewType.DATA.ordinal
} }
override fun indexForRow(row: RowRepresentable): Int { override fun indexForRow(row: RowRepresentable): Int {

@ -13,6 +13,9 @@ import kotlinx.android.synthetic.main.fragment_history.*
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.model.filter.FilterManager
import net.pokeranalytics.android.model.filter.Filterable
import net.pokeranalytics.android.model.filter.SessionFilterable
import net.pokeranalytics.android.model.interfaces.Manageable import net.pokeranalytics.android.model.interfaces.Manageable
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.activity.SessionActivity import net.pokeranalytics.android.ui.activity.SessionActivity
@ -92,6 +95,7 @@ class HistoryFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSource
* Init data * Init data
*/ */
private fun initData() { private fun initData() {
//realmSessions = FilterManager().filter(getRealm(), Session::class.java, arrayListOf<Filterable>(SessionFilterable.ONLINE, SessionFilterable.CASH)).sort("creationDate", Sort.DESCENDING) as RealmResults<Session>
realmSessions = getRealm().where<Session>().findAll().sort("creationDate", Sort.DESCENDING) realmSessions = getRealm().where<Session>().findAll().sort("creationDate", Sort.DESCENDING)
val viewManager = SmoothScrollLinearLayoutManager(requireContext()) val viewManager = SmoothScrollLinearLayoutManager(requireContext())

@ -20,7 +20,8 @@ import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.rowrepresentable.SettingRow import net.pokeranalytics.android.ui.view.rowrepresentable.SettingRow
import net.pokeranalytics.android.util.* import net.pokeranalytics.android.util.Preferences
import net.pokeranalytics.android.util.URL
import net.pokeranalytics.android.util.extensions.openContactMail import net.pokeranalytics.android.util.extensions.openContactMail
import net.pokeranalytics.android.util.extensions.openPlayStorePage import net.pokeranalytics.android.util.extensions.openPlayStorePage
import net.pokeranalytics.android.util.extensions.openUrl import net.pokeranalytics.android.util.extensions.openUrl
@ -43,17 +44,17 @@ class SettingsFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, Sta
return fragment return fragment
} }
val rowRepresentation : List<RowRepresentable> by lazy { val rowRepresentation: List<RowRepresentable> by lazy {
val rows = ArrayList<RowRepresentable>() val rows = ArrayList<RowRepresentable>()
rows.addAll(SettingRow.getRows()) rows.addAll(SettingRow.getRows())
rows rows
} }
val REQUEST_CODE_CURRENCY : Int = 0 const val REQUEST_CODE_CURRENCY: Int = 100
} }
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(row: RowRepresentable): String {
return when(row) { return when (row) {
SettingRow.VERSION -> BuildConfig.VERSION_NAME + if (BuildConfig.DEBUG) " DEBUG" else "" SettingRow.VERSION -> BuildConfig.VERSION_NAME + if (BuildConfig.DEBUG) " DEBUG" else ""
SettingRow.CURRENCY -> Currency.getInstance(Preferences.getCurrencyLocale(this.parentActivity)).symbol SettingRow.CURRENCY -> Currency.getInstance(Preferences.getCurrencyLocale(this.parentActivity)).symbol
@ -75,7 +76,10 @@ class SettingsFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, Sta
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == SettingsFragment.REQUEST_CODE_CURRENCY && resultCode == Activity.RESULT_OK) { if (requestCode == SettingsFragment.REQUEST_CODE_CURRENCY && resultCode == Activity.RESULT_OK) {
settingsAdapterRow.refreshRow(SettingRow.CURRENCY) data?.let {
Preferences.setCurrencyCode(data.getStringExtra(CurrenciesFragment.INTENT_CURRENCY_CODE), requireContext())
settingsAdapterRow.refreshRow(SettingRow.CURRENCY)
}
} }
} }
@ -89,13 +93,9 @@ class SettingsFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, Sta
SettingRow.RATE_APP -> parentActivity.openPlayStorePage() SettingRow.RATE_APP -> parentActivity.openPlayStorePage()
SettingRow.CONTACT_US -> parentActivity.openContactMail(R.string.contact) SettingRow.CONTACT_US -> parentActivity.openContactMail(R.string.contact)
SettingRow.BUG_REPORT -> parentActivity.openContactMail(R.string.bug_report_subject) SettingRow.BUG_REPORT -> parentActivity.openContactMail(R.string.bug_report_subject)
SettingRow.CURRENCY -> { SettingRow.CURRENCY -> CurrenciesActivity.newInstanceForResult(this@SettingsFragment, SettingsFragment.REQUEST_CODE_CURRENCY)
val intent = Intent(context, CurrenciesActivity::class.java)
this.startActivityForResult(intent, SettingsFragment.REQUEST_CODE_CURRENCY)
// CurrenciesActivity.newInstance(requireContext())
}
SettingRow.FOLLOW_US -> { SettingRow.FOLLOW_US -> {
when(position) { when (position) {
0 -> parentActivity.openUrl(URL.BLOG.value) 0 -> parentActivity.openUrl(URL.BLOG.value)
1 -> parentActivity.openUrl(URL.INSTAGRAM.value) 1 -> parentActivity.openUrl(URL.INSTAGRAM.value)
2 -> parentActivity.openUrl(URL.TWITTER.value) 2 -> parentActivity.openUrl(URL.TWITTER.value)

@ -0,0 +1,89 @@
package net.pokeranalytics.android.ui.fragment
import android.os.Bundle
import android.view.View
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.realm.Transaction
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.helpers.DateTimePickerManager
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.rowrepresentable.TransactionRow
import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.extensions.round
import net.pokeranalytics.android.util.extensions.shortDate
import java.util.*
/**
* Custom EditableDataFragment to manage the Transaction data
*/
class TransactionDataFragment : EditableDataFragment(), StaticRowRepresentableDataSource {
// Return the item as a Transaction object
private val transaction: Transaction
get() {
return this.item as Transaction
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
shouldOpenKeyboard = false
}
override fun getDataSource(): RowRepresentableDataSource {
return this
}
override fun adapterRows(): List<RowRepresentable>? {
return transaction.adapterRows()
}
override fun stringForRow(row: RowRepresentable): String {
return when (row) {
TransactionRow.BANKROLL -> this.transaction.bankroll?.name ?: NULL_TEXT
TransactionRow.TYPE -> this.transaction.type?.name ?: NULL_TEXT
TransactionRow.AMOUNT -> if (this.transaction.amount != 0.0) this.transaction.amount.round() else NULL_TEXT
TransactionRow.COMMENT -> if (this.transaction.comment.isNotEmpty()) this.transaction.comment else NULL_TEXT
TransactionRow.DATE -> this.transaction.date.shortDate()
else -> super.stringForRow(row)
}
}
override fun editDescriptors(row: RowRepresentable): ArrayList<RowRepresentableEditDescriptor>? {
return when (row) {
TransactionRow.BANKROLL -> row.editingDescriptors(mapOf("defaultValue" to this.transaction.bankroll, "data" to LiveData.BANKROLL.items(getRealm())))
TransactionRow.TYPE -> row.editingDescriptors(mapOf("defaultValue" to this.transaction.type, "data" to LiveData.TRANSACTION_TYPE.items(getRealm())))
TransactionRow.AMOUNT -> row.editingDescriptors(mapOf("defaultValue" to (if (this.transaction.amount != 0.0) this.transaction.amount.round() else "")))
TransactionRow.COMMENT -> row.editingDescriptors(mapOf("defaultValue" to this.transaction.comment))
else -> super.editDescriptors(row)
}
}
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
when (row) {
TransactionRow.DATE -> DateTimePickerManager.create(requireContext(), row, this, this.transaction.date, onlyDate = true, isClearable = false)
else -> super.onRowSelected(position, row, fromAction)
}
}
override fun onRowValueChanged(value: Any?, row: RowRepresentable) {
super.onRowValueChanged(value, row)
rowRepresentableAdapter.refreshRow(row)
GlobalScope.launch(Dispatchers.Main) {
delay(200)
when(row) {
TransactionRow.BANKROLL -> onRowSelected(0, TransactionRow.TYPE)
TransactionRow.TYPE -> onRowSelected(0, TransactionRow.AMOUNT)
TransactionRow.AMOUNT -> onRowSelected(0, TransactionRow.COMMENT)
TransactionRow.COMMENT -> onRowSelected(0, TransactionRow.DATE)
}
}
}
}

@ -21,6 +21,7 @@ import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
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.SessionRow import net.pokeranalytics.android.ui.view.rowrepresentable.SessionRow
import net.pokeranalytics.android.ui.view.rowrepresentable.TransactionRow
open class BottomSheetFragment : BottomSheetDialogFragment() { open class BottomSheetFragment : BottomSheetDialogFragment() {
@ -111,7 +112,7 @@ open class BottomSheetFragment : BottomSheetDialogFragment() {
LiveData.GAME.ordinal, LiveData.GAME.ordinal,
requestCode = REQUEST_CODE_ADD_NEW_OBJECT requestCode = REQUEST_CODE_ADD_NEW_OBJECT
) )
SessionRow.BANKROLL -> EditableDataActivity.newInstanceForResult( SessionRow.BANKROLL, TransactionRow.BANKROLL -> EditableDataActivity.newInstanceForResult(
this, this,
LiveData.BANKROLL.ordinal, LiveData.BANKROLL.ordinal,
requestCode = REQUEST_CODE_ADD_NEW_OBJECT requestCode = REQUEST_CODE_ADD_NEW_OBJECT
@ -131,6 +132,11 @@ open class BottomSheetFragment : BottomSheetDialogFragment() {
LiveData.TOURNAMENT_FEATURE.ordinal, LiveData.TOURNAMENT_FEATURE.ordinal,
requestCode = REQUEST_CODE_ADD_NEW_OBJECT requestCode = REQUEST_CODE_ADD_NEW_OBJECT
) )
TransactionRow.TYPE -> EditableDataActivity.newInstanceForResult(
this,
LiveData.TRANSACTION_TYPE.ordinal,
requestCode = REQUEST_CODE_ADD_NEW_OBJECT
)
} }
true true
} }

@ -22,15 +22,19 @@ class DateTimePickerManager : DatePickerDialog.OnDateSetListener,
private lateinit var delegate: RowRepresentableDelegate private lateinit var delegate: RowRepresentableDelegate
private lateinit var calendar: Calendar private lateinit var calendar: Calendar
private var minimumDate: Date? = null private var minimumDate: Date? = null
private var onlyDate: Boolean = false
private var isClearable: Boolean = true
companion object { companion object {
fun create( fun create(
context: Context, context: Context,
row: RowRepresentable, row: RowRepresentable,
delegate: RowRepresentableDelegate, delegate: RowRepresentableDelegate,
date: Date?, date: Date?,
minimumDate: Date? = null minimumDate: Date? = null,
) : DateTimePickerManager { onlyDate: Boolean? = false,
isClearable: Boolean? = true
): DateTimePickerManager {
val calendar = Calendar.getInstance() val calendar = Calendar.getInstance()
calendar.time = date ?: Date() calendar.time = date ?: Date()
@ -41,6 +45,8 @@ class DateTimePickerManager : DatePickerDialog.OnDateSetListener,
dateTimePickerManager.delegate = delegate dateTimePickerManager.delegate = delegate
dateTimePickerManager.calendar = calendar dateTimePickerManager.calendar = calendar
dateTimePickerManager.minimumDate = minimumDate dateTimePickerManager.minimumDate = minimumDate
dateTimePickerManager.onlyDate = onlyDate ?: false
dateTimePickerManager.isClearable = isClearable ?: true
dateTimePickerManager.showDatePicker() dateTimePickerManager.showDatePicker()
@ -52,7 +58,11 @@ class DateTimePickerManager : DatePickerDialog.OnDateSetListener,
calendar.set(Calendar.YEAR, year) calendar.set(Calendar.YEAR, year)
calendar.set(Calendar.MONTH, month) calendar.set(Calendar.MONTH, month)
calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth) calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth)
showTimePicker() if (!onlyDate) {
showTimePicker()
} else {
delegate.onRowValueChanged(calendar.time, row)
}
} }
override fun onTimeSet(view: TimePicker?, hourOfDay: Int, minute: Int) { override fun onTimeSet(view: TimePicker?, hourOfDay: Int, minute: Int) {
@ -86,10 +96,13 @@ class DateTimePickerManager : DatePickerDialog.OnDateSetListener,
datePickerDialog.datePicker.minDate = it.time datePickerDialog.datePicker.minDate = it.time
} }
datePickerDialog.setButton(DialogInterface.BUTTON_NEGATIVE, it.getString(R.string.clear)) { dialog, _ -> if (isClearable) {
delegate.onRowValueChanged(null, row) datePickerDialog.setButton(DialogInterface.BUTTON_NEGATIVE, it.getString(R.string.clear)) { dialog, _ ->
dialog.dismiss() delegate.onRowValueChanged(null, row)
dialog.dismiss()
}
} }
datePickerDialog.show() datePickerDialog.show()
} }
} }

@ -11,8 +11,10 @@ import androidx.core.view.isVisible
import androidx.core.widget.ContentLoadingProgressBar import androidx.core.widget.ContentLoadingProgressBar
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.row_history_session.view.* import kotlinx.android.synthetic.main.row_history_session.view.*
import kotlinx.android.synthetic.main.row_transaction.view.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.Transaction
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
@ -52,6 +54,7 @@ enum class RowViewType(private var layoutRes: Int) {
// Custom row // Custom row
ROW_SESSION(R.layout.row_history_session), ROW_SESSION(R.layout.row_history_session),
ROW_TRANSACTION(R.layout.row_transaction),
ROW_BUTTON(R.layout.row_button), ROW_BUTTON(R.layout.row_button),
ROW_FOLLOW_US(R.layout.row_follow_us), ROW_FOLLOW_US(R.layout.row_follow_us),
STAT(R.layout.row_stats_title_value), STAT(R.layout.row_stats_title_value),
@ -79,6 +82,9 @@ enum class RowViewType(private var layoutRes: Int) {
// Row Session // Row Session
ROW_SESSION -> RowSessionViewHolder(layout) ROW_SESSION -> RowSessionViewHolder(layout)
// Row Transaction
ROW_TRANSACTION -> RowTransactionViewHolder(layout)
// Row Button // Row Button
ROW_BUTTON -> RowButtonViewHolder(layout) ROW_BUTTON -> RowButtonViewHolder(layout)
@ -257,6 +263,19 @@ enum class RowViewType(private var layoutRes: Int) {
} }
} }
/**
* Display a transaction view
*/
inner class RowTransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
itemView.transactionRow.setData(row as Transaction)
val listener = View.OnClickListener {
adapter.delegate?.onRowSelected(position, row)
}
itemView.transactionRow.setOnClickListener(listener)
}
}
/** /**
* Display a separator * Display a separator
*/ */

@ -0,0 +1,71 @@
package net.pokeranalytics.android.ui.view
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.FrameLayout
import androidx.constraintlayout.widget.ConstraintLayout
import kotlinx.android.synthetic.main.row_transaction_view.view.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.ComputedStat
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.model.realm.Transaction
import net.pokeranalytics.android.util.extensions.getDayNumber
import net.pokeranalytics.android.util.extensions.getShortDayName
/**
* Display a transaction row
*/
class TransactionRowView : FrameLayout {
private lateinit var rowTransaction: ConstraintLayout
/**
* Constructors
*/
constructor(context: Context) : super(context) {
init()
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
init()
}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
init()
}
/**
* Init
*/
private fun init() {
val layoutInflater = LayoutInflater.from(context)
rowTransaction = layoutInflater.inflate(R.layout.row_transaction_view, this, false) as ConstraintLayout
val layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT)
addView(rowTransaction, layoutParams)
}
/**
* Set the session data to the view
*/
fun setData(transaction: Transaction) {
// Date
rowTransaction.transactionDateDay.text = transaction.date.getShortDayName()
rowTransaction.transactionDateNumber.text = transaction.date.getDayNumber()
// Title / Game type
var title = transaction.type?.name ?: "" + " " + transaction.comment
var subtitle = transaction.bankroll?.name
rowTransaction.transactionTitle.text = title
rowTransaction.transactionSubtitle.text = subtitle
// Amount
val formattedStat = ComputedStat(Stat.NETRESULT, transaction.amount).format(context)
rowTransaction.transactionAmount.setTextColor(formattedStat.getColor(context))
rowTransaction.transactionAmount.text = formattedStat.text
}
}

@ -1,19 +1,27 @@
package net.pokeranalytics.android.ui.view.rowrepresentable package net.pokeranalytics.android.ui.view.rowrepresentable
import android.text.InputType
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType
import net.pokeranalytics.android.ui.view.DefaultEditable import net.pokeranalytics.android.ui.view.DefaultEditable
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.RowViewType import net.pokeranalytics.android.ui.view.RowViewType
enum class BankrollRow : RowRepresentable, DefaultEditable { enum class BankrollRow : RowRepresentable, DefaultEditable {
LIVE; LIVE,
CURRENCY,
RATE,
REFRESH_RATE;
override val resId: Int? override val resId: Int?
get() { get() {
return when (this) { return when (this) {
LIVE -> R.string.online LIVE -> R.string.online
CURRENCY -> R.string.currency
RATE -> R.string.rate
REFRESH_RATE -> R.string.refresh_rate
} }
} }
@ -21,6 +29,9 @@ enum class BankrollRow : RowRepresentable, DefaultEditable {
get() { get() {
return when (this) { return when (this) {
LIVE -> RowViewType.TITLE_SWITCH.ordinal LIVE -> RowViewType.TITLE_SWITCH.ordinal
CURRENCY -> RowViewType.TITLE_VALUE_ARROW.ordinal
RATE -> RowViewType.TITLE_VALUE.ordinal
REFRESH_RATE -> RowViewType.ROW_BUTTON.ordinal
} }
} }
@ -28,7 +39,22 @@ enum class BankrollRow : RowRepresentable, DefaultEditable {
get() { get() {
return when (this) { return when (this) {
LIVE -> BottomSheetType.NONE LIVE -> BottomSheetType.NONE
CURRENCY -> BottomSheetType.NONE
RATE -> BottomSheetType.EDIT_TEXT
REFRESH_RATE -> BottomSheetType.NONE
} }
} }
override fun editingDescriptors(map: Map<String, Any?>): ArrayList<RowRepresentableEditDescriptor>? {
return when (this) {
BankrollRow.RATE -> {
val defaultValue : Any? by map
arrayListOf(
RowRepresentableEditDescriptor(defaultValue, R.string.rate, InputType.TYPE_CLASS_NUMBER
or InputType.TYPE_NUMBER_FLAG_DECIMAL)
)
}
else -> super<RowRepresentable>.editingDescriptors(map)
}
}
} }

@ -150,8 +150,8 @@ enum class SessionRow : RowRepresentable {
override fun editingDescriptors(map: Map<String, Any?>): ArrayList<RowRepresentableEditDescriptor>? { override fun editingDescriptors(map: Map<String, Any?>): ArrayList<RowRepresentableEditDescriptor>? {
return when (this) { return when (this) {
BLINDS -> { BLINDS -> {
val sb: Double? by map val sb: String? by map
val bb: Double? by map val bb: String? by map
arrayListOf( arrayListOf(
RowRepresentableEditDescriptor(sb, R.string.smallblind, InputType.TYPE_CLASS_NUMBER RowRepresentableEditDescriptor(sb, R.string.smallblind, InputType.TYPE_CLASS_NUMBER
or InputType.TYPE_NUMBER_FLAG_DECIMAL), or InputType.TYPE_NUMBER_FLAG_DECIMAL),
@ -190,18 +190,18 @@ enum class SessionRow : RowRepresentable {
data data
} }
CASHED_OUT, PRIZE, NET_RESULT -> { CASHED_OUT, PRIZE, NET_RESULT -> {
val cashout: Double? by map val defaultValue: String? by map
arrayListOf( arrayListOf(
RowRepresentableEditDescriptor( RowRepresentableEditDescriptor(
cashout?.round(), defaultValue,
inputType = InputType.TYPE_CLASS_NUMBER inputType = InputType.TYPE_CLASS_NUMBER
or InputType.TYPE_NUMBER_FLAG_DECIMAL or InputType.TYPE_NUMBER_FLAG_DECIMAL
or InputType.TYPE_NUMBER_FLAG_SIGNED or InputType.TYPE_NUMBER_FLAG_SIGNED
)) ))
} }
COMMENT -> { COMMENT -> {
val comment : String? by map val defaultValue : String? by map
arrayListOf(RowRepresentableEditDescriptor(comment, R.string.comment)) arrayListOf(RowRepresentableEditDescriptor(defaultValue, R.string.comment))
} }
BREAK_TIME -> { BREAK_TIME -> {
arrayListOf( arrayListOf(
@ -220,9 +220,9 @@ enum class SessionRow : RowRepresentable {
RowRepresentableEditDescriptor(defaultValue, data = data)) RowRepresentableEditDescriptor(defaultValue, data = data))
} }
INITIAL_BUY_IN -> { INITIAL_BUY_IN -> {
val fee : Double? by map val defaultValue : Double? by map
arrayListOf( arrayListOf(
RowRepresentableEditDescriptor(fee?.round(), inputType = InputType.TYPE_CLASS_NUMBER) RowRepresentableEditDescriptor(defaultValue?.round(), inputType = InputType.TYPE_CLASS_NUMBER)
) )
} }
BANKROLL, LOCATION, TOURNAMENT_FEATURE, TOURNAMENT_NAME -> { BANKROLL, LOCATION, TOURNAMENT_FEATURE, TOURNAMENT_NAME -> {
@ -233,30 +233,30 @@ enum class SessionRow : RowRepresentable {
) )
} }
PLAYERS -> { PLAYERS -> {
val tournamentNumberOfPlayers: Int? by map val defaultValue: Int? by map
arrayListOf( arrayListOf(
RowRepresentableEditDescriptor( RowRepresentableEditDescriptor(
tournamentNumberOfPlayers?.toString(), defaultValue?.toString(),
inputType = InputType.TYPE_CLASS_NUMBER inputType = InputType.TYPE_CLASS_NUMBER
) )
) )
} }
POSITION -> { POSITION -> {
val tournamentFinalPosition : Int? by map val defaultValue : Int? by map
arrayListOf( arrayListOf(
RowRepresentableEditDescriptor( RowRepresentableEditDescriptor(
tournamentFinalPosition, defaultValue,
inputType = InputType.TYPE_CLASS_NUMBER inputType = InputType.TYPE_CLASS_NUMBER
) )
) )
} }
TABLE_SIZE -> { TABLE_SIZE -> {
val tableSize : Int? by map val defaultValue : Int? by map
arrayListOf(RowRepresentableEditDescriptor(tableSize)) arrayListOf(RowRepresentableEditDescriptor(defaultValue))
} }
TIPS -> { TIPS -> {
val sb: Double? by map val sb: String? by map
val bb: Double? by map val bb: String? by map
val tips: Double? by map val tips: Double? by map
// Disable the buttons with value = 0, add current value & set the 2 edit texts // Disable the buttons with value = 0, add current value & set the 2 edit texts

@ -26,6 +26,7 @@ enum class SettingRow : RowRepresentable {
LOCATION, LOCATION,
TOURNAMENT_NAME, TOURNAMENT_NAME,
TOURNAMENT_FEATURE, TOURNAMENT_FEATURE,
TRANSACTION,
// Terms // Terms
PRIVACY_POLICY, PRIVACY_POLICY,
@ -55,7 +56,7 @@ enum class SettingRow : RowRepresentable {
resId = R.string.data_management resId = R.string.data_management
) )
) )
rows.addAll(arrayListOf(BANKROLL, GAME, LOCATION, TOURNAMENT_NAME, TOURNAMENT_FEATURE)) rows.addAll(arrayListOf(BANKROLL, GAME, LOCATION, TOURNAMENT_NAME, TOURNAMENT_FEATURE, TRANSACTION))
rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.terms)) rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.terms))
rows.addAll(arrayListOf(PRIVACY_POLICY, TERMS_OF_USE, GDPR)) rows.addAll(arrayListOf(PRIVACY_POLICY, TERMS_OF_USE, GDPR))
@ -104,6 +105,7 @@ enum class SettingRow : RowRepresentable {
LOCATION -> LiveData.LOCATION LOCATION -> LiveData.LOCATION
TOURNAMENT_NAME -> LiveData.TOURNAMENT_NAME TOURNAMENT_NAME -> LiveData.TOURNAMENT_NAME
TOURNAMENT_FEATURE -> LiveData.TOURNAMENT_FEATURE TOURNAMENT_FEATURE -> LiveData.TOURNAMENT_FEATURE
TRANSACTION -> LiveData.TRANSACTION
else -> null else -> null
} }
} }

@ -0,0 +1,86 @@
package net.pokeranalytics.android.ui.view.rowrepresentable
import android.text.InputType
import io.realm.RealmResults
import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType
import net.pokeranalytics.android.ui.view.DefaultEditable
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.RowViewType
enum class TransactionRow : RowRepresentable, DefaultEditable {
BANKROLL,
TYPE,
AMOUNT,
COMMENT,
DATE;
override val resId: Int?
get() {
return when (this) {
BANKROLL -> R.string.bankroll
TYPE -> R.string.type
AMOUNT -> R.string.amount
COMMENT -> R.string.comment
DATE -> R.string.date
}
}
override val viewType: Int
get() {
return when (this) {
BANKROLL -> RowViewType.TITLE_VALUE.ordinal
TYPE -> RowViewType.TITLE_VALUE.ordinal
AMOUNT -> RowViewType.TITLE_VALUE.ordinal
COMMENT -> RowViewType.TITLE_VALUE.ordinal
DATE -> RowViewType.TITLE_VALUE.ordinal
}
}
override val bottomSheetType: BottomSheetType
get() {
return when (this) {
BANKROLL -> BottomSheetType.LIST
TYPE -> BottomSheetType.LIST
AMOUNT -> BottomSheetType.EDIT_TEXT
COMMENT -> BottomSheetType.EDIT_TEXT_MULTI_LINES
DATE -> BottomSheetType.NONE
}
}
override fun editingDescriptors(map: Map<String, Any?>): ArrayList<RowRepresentableEditDescriptor>? {
return when (this) {
BANKROLL -> {
val defaultValue : Any? by map
val data : RealmResults<*>? by map
arrayListOf(
RowRepresentableEditDescriptor(defaultValue, data = data)
)
}
TYPE -> {
val defaultValue : Any? by map
val data : RealmResults<*>? by map
arrayListOf(
RowRepresentableEditDescriptor(defaultValue, data = data)
)
}
AMOUNT -> {
val defaultValue: String? by map
arrayListOf(
RowRepresentableEditDescriptor(
defaultValue,
inputType = InputType.TYPE_CLASS_NUMBER
or InputType.TYPE_NUMBER_FLAG_DECIMAL
or InputType.TYPE_NUMBER_FLAG_SIGNED
))
}
COMMENT -> {
val defaultValue : String? by map
arrayListOf(RowRepresentableEditDescriptor(defaultValue, R.string.comment))
}
else -> super<RowRepresentable>.editingDescriptors(map)
}
}
}

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<net.pokeranalytics.android.ui.view.TransactionRowView
android:id="@+id/transactionRow"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="?selectableItemBackground">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/transactionDateDay"
style="@style/PokerAnalyticsTheme.TextView.SessionRow.Date"
android:layout_width="32dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:textAllCaps="true"
app:fontFamily="@font/roboto_mono_medium"
app:layout_constraintBottom_toTopOf="@+id/transactionDateNumber"
app:layout_constraintStart_toStartOf="@+id/guidelineStart"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="THU" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/transactionDateNumber"
style="@style/PokerAnalyticsTheme.TextView.SessionRow.DateNumber"
android:layout_width="32dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/transactionDateDay"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/transactionDateDay"
app:layout_constraintTop_toBottomOf="@+id/transactionDateDay"
tools:text="21" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/transactionTitle"
style="@style/PokerAnalyticsTheme.TextView.SessionRow.Title"
android:layout_width="0dp"
android:layout_height="24dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toTopOf="@+id/transactionSubtitle"
app:layout_constraintEnd_toStartOf="@+id/transactionAmount"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/transactionDateDay"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Deposit: Live" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/transactionSubtitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginBottom="2dp"
android:ellipsize="end"
android:fontFamily="@font/roboto"
android:maxLines="1"
android:textColor="@color/kaki_lighter"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/transactionAmount"
app:layout_constraintStart_toStartOf="@+id/transactionTitle"
app:layout_constraintTop_toBottomOf="@+id/transactionTitle"
tools:text="Live"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/transactionAmount"
style="@style/PokerAnalyticsTheme.TextView.SessionRow.Result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="@+id/transactionSubtitle"
app:layout_constraintEnd_toStartOf="@+id/nextArrow"
app:layout_constraintTop_toTopOf="@+id/transactionTitle"
tools:text="$ 1000" />
<ImageView
android:id="@+id/nextArrow"
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/ic_arrow_right"
android:tint="@color/gray_light"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/guidelineEnd"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guidelineStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="16dp" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guidelineEnd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="8dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -8,12 +8,23 @@ import org.junit.Assert.assertThat
import org.junit.Before import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith
import org.powermock.api.mockito.PowerMockito import org.powermock.api.mockito.PowerMockito
import org.powermock.api.mockito.PowerMockito.`when` import org.powermock.api.mockito.PowerMockito.`when`
import org.powermock.api.mockito.PowerMockito.mockStatic import org.powermock.api.mockito.PowerMockito.mockStatic
import org.powermock.core.classloader.annotations.PowerMockIgnore
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor
import org.powermock.modules.junit4.rule.PowerMockRule import org.powermock.modules.junit4.rule.PowerMockRule
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
@RunWith(RobolectricTestRunner::class)
@Config(manifest = Config.NONE, sdk = [19])
@PowerMockIgnore("org.mockito.*", "org.robolectric.*", "android.*")
@SuppressStaticInitializationFor("io.realm.internal.Util")
@PrepareForTest(Realm::class, RealmLog::class)
open class RealmUnitTest { open class RealmUnitTest {
@get:Rule @get:Rule

Loading…
Cancel
Save