First working implementation of transaction filters

currency
Laurent 3 years ago
parent 08167f721a
commit aa2e144fb9
  1. 5
      app/src/main/AndroidManifest.xml
  2. 2
      app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt
  3. 31
      app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt
  4. 18
      app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt
  5. 2
      app/src/main/java/net/pokeranalytics/android/exceptions/Exceptions.kt
  6. 9
      app/src/main/java/net/pokeranalytics/android/model/filter/Query.kt
  7. 12
      app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt
  8. 21
      app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt
  9. 12
      app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt
  10. 13
      app/src/main/java/net/pokeranalytics/android/model/realm/UserConfig.kt
  11. 86
      app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt
  12. 5
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/FilterableFragment.kt
  13. 12
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/RealmFragment.kt
  14. 2
      app/src/main/java/net/pokeranalytics/android/ui/modules/settings/DealtHandsPerHourFragment.kt
  15. 25
      app/src/main/java/net/pokeranalytics/android/ui/modules/settings/TransactionFilterActivity.kt
  16. 132
      app/src/main/java/net/pokeranalytics/android/ui/modules/settings/TransactionFilterFragment.kt
  17. 19
      app/src/main/java/net/pokeranalytics/android/ui/modules/settings/TransactionFilterViewModel.kt
  18. 1
      app/src/main/java/net/pokeranalytics/android/util/Global.kt
  19. 26
      app/src/main/java/net/pokeranalytics/android/util/Preferences.kt
  20. 10
      app/src/main/res/drawable-xxhdpi/baseline_payment_24.xml
  21. 15
      app/src/main/res/layout/activity_transaction_filter.xml
  22. 30
      app/src/main/res/layout/fragment_settings.xml
  23. 59
      app/src/main/res/layout/fragment_transaction_filter.xml
  24. 0
      app/src/main/res/menu/toolbar_save.xml
  25. 1
      app/src/main/res/values-fr/strings.xml
  26. 1
      app/src/main/res/values/ids.xml
  27. 1
      app/src/main/res/values/strings.xml

@ -176,6 +176,11 @@
android:launchMode="singleTop"
android:screenOrientation="portrait" />
<activity
android:name="net.pokeranalytics.android.ui.modules.settings.TransactionFilterActivity"
android:launchMode="singleTop"
android:screenOrientation="portrait" />
<!-- No screenOrientation="portrait" to fix Oreo crash -->
<activity
android:name="net.pokeranalytics.android.ui.activity.ColorPickerActivity"

@ -50,7 +50,7 @@ class PokerAnalyticsApplication : Application() {
Realm.init(this)
val realmConfiguration = RealmConfiguration.Builder()
.name(Realm.DEFAULT_REALM_NAME)
.schemaVersion(13)
.schemaVersion(14)
.allowWritesOnUiThread(true)
.migration(PokerAnalyticsMigration())
.initialData(Seed(this))

@ -9,9 +9,7 @@ import net.pokeranalytics.android.model.combined
import net.pokeranalytics.android.model.extensions.hourlyDuration
import net.pokeranalytics.android.model.filter.Query
import net.pokeranalytics.android.model.filter.filter
import net.pokeranalytics.android.model.realm.ComputableResult
import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.model.realm.SessionSet
import net.pokeranalytics.android.model.realm.*
import net.pokeranalytics.android.util.extensions.startOfDay
import java.util.*
import kotlin.math.max
@ -35,7 +33,8 @@ class Calculator {
var filterId: String? = null,
private var aggregationType: AggregationType? = null,
var userGenerated: Boolean = false,
var reportSetupId: String? = null
var reportSetupId: String? = null,
var includedTransactions: List<TransactionType> = listOf()
) {
constructor(
@ -252,8 +251,16 @@ class Calculator {
// Timber.d("$$$ buyin = ${it.ratedBuyin} $$$ net result = ${it.ratedNet}")
// }
val sum = computables.sum(ComputableResult.Field.RATED_NET.identifier).toDouble()
results.addStat(NET_RESULT, sum)
var ratedNet = computables.sum(ComputableResult.Field.RATED_NET.identifier).toDouble()
if (options.includedTransactions.isNotEmpty()) {
for (transactionType in options.includedTransactions) {
val transactions = computableGroup.transactions(realm, transactionType, options.shouldSortValues)
val transactionRatedAmount = transactions.sum(Transaction.Field.RATED_AMOUNT.identifier).toDouble()
ratedNet += transactionRatedAmount
}
}
results.addStat(NET_RESULT, ratedNet)
val totalHands = computables.sum(ComputableResult.Field.ESTIMATED_HANDS.identifier).toDouble()
results.addStat(HANDS_PLAYED, totalHands)
@ -288,7 +295,7 @@ class Calculator {
Stat.netBBPer100Hands(bbSum, totalHands)?.let { netBB100 ->
results.addStat(NET_BB_PER_100_HANDS, netBB100)
}
Stat.returnOnInvestment(sum, totalBuyin)?.let { roi ->
Stat.returnOnInvestment(ratedNet, totalBuyin)?.let { roi ->
results.addStat(ROI, roi)
}
@ -305,7 +312,7 @@ class Calculator {
var average = 0.0 // also used for standard deviation later
if (computables.size > 0) {
average = sum / computables.size.toDouble()
average = ratedNet / computables.size.toDouble()
val winRatio = winningSessionCount.toDouble() / computables.size.toDouble()
val itmRatio = winningSessionCount.toDouble() / computables.size.toDouble()
val avgBuyin = totalBuyin / computables.size.toDouble()
@ -425,9 +432,9 @@ class Calculator {
}
}
val shouldIterateOverSets = computableGroup.conditions.isNotEmpty() ||
options.progressValues != Options.ProgressValues.NONE ||
options.computeDaysPlayed
val shouldIterateOverSets = computableGroup.conditions.isNotEmpty()
|| options.progressValues != Options.ProgressValues.NONE
|| options.computeDaysPlayed
// Session Set
if (shouldIterateOverSets) {
@ -525,7 +532,7 @@ class Calculator {
var hourlyRate = 0.0
if (gHourlyDuration != null) {
hourlyRate = sum / gHourlyDuration
hourlyRate = ratedNet / gHourlyDuration
if (sessionSets.size > 0) {
val avgDuration = gHourlyDuration / sessionSets.size
results.addStat(HOURLY_RATE, hourlyRate)

@ -4,15 +4,14 @@ 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
import net.pokeranalytics.android.model.realm.*
import timber.log.Timber
/**
* A sessionGroup of computable items identified by a name
*/
class ComputableGroup(var query: Query, var displayedStats: List<Stat>? = null) {
class ComputableGroup(val query: Query, var displayedStats: List<Stat>? = null) {
/**
* A subgroup used to compute stat variation
@ -85,6 +84,17 @@ class ComputableGroup(var query: Query, var displayedStats: List<Stat>? = null)
return sets
}
/**
* Retrieves the transactions on the relative [realm] filtered with the provided [conditions]
*/
fun transactions(realm: Realm, transactionType: TransactionType, sorted: Boolean = false): RealmResults<Transaction> {
val query = this.query.copy()
query.add(QueryCondition.AnyTransactionType(transactionType))
val sortedField = if (sorted) "date" else null
Timber.d("query = ${query.defaultName}")
return Filter.queryOn(realm, query, sortedField)
}
/**
* Nullifies used Realm results
*/

@ -17,7 +17,7 @@ sealed class PokerAnalyticsException(message: String) : Exception(message) {
// object FilterElementUnknownSectionName: PokerAnalyticsException(message = "No filterElement section name was found to identify the queryCondition")
// object FilterMissingEntity: PokerAnalyticsException(message = "This queryWith has no entity initialized")
// object FilterUnhandledEntity : PokerAnalyticsException(message = "This entity is not filterable")
object QueryValueMapUnknown: PokerAnalyticsException(message = "fieldName is missing")
class QueryValueMapUnknown(message: String = "fieldName is missing"): PokerAnalyticsException(message)
class QueryTypeUnhandled(clazz: String) :
PokerAnalyticsException(message = "queryWith type not handled: $clazz")
class ComparisonCriteriaUnhandled(criteria: Criteria) :

@ -11,6 +11,10 @@ fun List<Query>.mapFirstCondition() : List<QueryCondition> {
class Query {
constructor(query: Query) {
this._conditions.addAll(query.conditions)
}
constructor(vararg elements: QueryCondition?) {
if (elements.isNotEmpty()) {
this.add(elements.filterNotNull())
@ -100,6 +104,11 @@ class Query {
return this
}
fun copy(): Query {
return Query(this)
}
/*
Returns the first object Id of any QueryCondition
*/

@ -23,6 +23,7 @@ import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.UserDefaults
import net.pokeranalytics.android.util.extensions.*
import timber.log.Timber
import java.text.DateFormatSymbols
import java.text.NumberFormat
import java.util.*
@ -747,9 +748,16 @@ sealed class QueryCondition : RowRepresentable {
): RealmQuery<T> {
val fieldName = FilterHelper.fieldNameForQueryType<T>(this::class.java)
if (BuildConfig.DEBUG) {
fieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown
// if (BuildConfig.DEBUG) {
// val className = T::class.java
// fieldName ?: throw PokerAnalyticsException.QueryValueMapUnknown("fieldName missing for $this, class = $className")
// }
if (fieldName == null) {
val className = T::class.java
Timber.w("Possible missing filter configuration for $this in class $className")
}
fieldName ?: return realmQuery
when (this) {

@ -292,11 +292,11 @@ class PokerAnalyticsMigration : RealmMigration {
// Migrate to version 13
if (currentVersion == 12) {
Timber.d("*** Running migration ${currentVersion + 1}")
schema.get("Transaction")?.let { tts ->
tts.addField("transferRate", Double::class.java)
schema.get("Transaction")?.let { ts ->
ts.addField("transferRate", Double::class.java)
.setNullable("transferRate", true)
schema.get("Bankroll")?.let { bs ->
tts.addRealmObjectField("destination", bs)
ts.addRealmObjectField("destination", bs)
} ?: throw PAIllegalStateException("Bankroll schema not found")
}
@ -314,6 +314,21 @@ class PokerAnalyticsMigration : RealmMigration {
currentVersion++
}
// Migrate to version 14
if (currentVersion == 13) {
Timber.d("*** Running migration ${currentVersion + 1}")
schema.get("Transaction")?.let { ts ->
ts.addField("ratedAmount", Double::class.java)
} ?: throw PAIllegalStateException("Transaction schema not found")
//transactionTypeIds
schema.get("UserConfig")?.let { ucs ->
ucs.addField("transactionTypeIds", String::class.java).setRequired("transactionTypeIds", true)
} ?: throw PAIllegalStateException("UserConfig schema not found")
currentVersion++
}
}
override fun equals(other: Any?): Boolean {

@ -73,6 +73,14 @@ open class Transaction : RealmObject(), RowRepresentable, RowUpdatable, Manageab
// The amount of the transaction
override var amount: Double = 0.0
set(value) {
field = value
val rate = this.bankroll?.currency?.rate ?: 1.0
this.ratedAmount = rate * value
}
// The amount of the transaction
var ratedAmount: Double = 0.0
// The date of the transaction
override var date: Date = Date()
@ -102,6 +110,10 @@ open class Transaction : RealmObject(), RowRepresentable, RowUpdatable, Manageab
@Ignore
override val viewType: Int = RowViewType.ROW_TRANSACTION.ordinal
enum class Field(val identifier: String) {
RATED_AMOUNT("ratedAmount")
}
val displayAmount: Double
get() { // for transfers we want to show a positive value (in the feed for instance)
return if (this.destination == null) { this.amount } else { abs(this.amount) }

@ -3,6 +3,8 @@ package net.pokeranalytics.android.model.realm
import io.realm.Realm
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import net.pokeranalytics.android.util.UUID_SEPARATOR
import net.pokeranalytics.android.util.extensions.findById
import java.util.*
open class UserConfig : RealmObject() {
@ -25,4 +27,15 @@ open class UserConfig : RealmObject() {
var onlineDealtHandsPerHour: Int = 500
var transactionTypeIds: String = ""
fun setTransactionTypeIds(transactionTypes: Set<TransactionType>) {
this.transactionTypeIds = transactionTypes.joinToString(UUID_SEPARATOR) { it.id }
}
fun transactionTypes(realm: Realm): List<TransactionType> {
val ids = this.transactionTypeIds.split(UUID_SEPARATOR)
return ids.mapNotNull { realm.findById(it) }
}
}

@ -2,11 +2,13 @@ package net.pokeranalytics.android.ui.fragment
import android.app.Activity
import android.content.Intent
import android.content.res.ColorStateList
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.*
import androidx.appcompat.widget.Toolbar
import io.realm.Realm
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
@ -19,16 +21,14 @@ import net.pokeranalytics.android.databinding.FragmentStatsBinding
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.realm.ComputableResult
import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.model.realm.Result
import net.pokeranalytics.android.model.realm.UserConfig
import net.pokeranalytics.android.model.realm.*
import net.pokeranalytics.android.ui.fragment.components.FilterableFragment
import net.pokeranalytics.android.ui.fragment.components.RealmAsyncListener
import net.pokeranalytics.android.ui.fragment.report.ComposableTableReportFragment
import net.pokeranalytics.android.ui.modules.filter.FilterActivityRequestCode
import net.pokeranalytics.android.ui.modules.filter.FilterableType
import net.pokeranalytics.android.ui.modules.filter.FiltersActivity
import net.pokeranalytics.android.ui.modules.settings.TransactionFilterActivity
import timber.log.Timber
import java.util.*
@ -36,6 +36,8 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
private lateinit var tableReportFragment: ComposableTableReportFragment
private var transactionFilterMenuItem: MenuItem? = null
companion object {
/**
@ -73,6 +75,7 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
addRealmChangeListener(this, UserConfig::class.java)
addRealmChangeListener(this, ComputableResult::class.java)
addRealmChangeListener(this, Transaction::class.java)
}
private fun initUI() {
@ -83,27 +86,41 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
this.tableReportFragment = fragment
}
// override val observedEntities: List<Class<out RealmModel>> = listOf(ComputableResult::class.java)
// override fun entitiesChanged(clazz: Class<out RealmModel>, results: RealmResults<out RealmModel>) {
// Timber.d("Entities changes, launch stats computation, size = ${results.size}")
// val cr = results as RealmResults<ComputableResult>
// cr.forEach {
// Timber.d("### buyin = ${it.ratedBuyin} ### net result = ${it.ratedNet}")
// }
// this.launchStatComputation()
// }
// override fun convertReportIntoRepresentables(report: Report): ArrayList<RowRepresentable> {
// val rows: ArrayList<RowRepresentable> = ArrayList()
// report.results.forEach { result ->
// rows.add(CustomizableRowRepresentable(title = result.group.name))
// result.group.stats?.forEach { stat ->
// rows.add(StatRow(stat, result.computedStat(stat), result.group.name))
// }
// }
// return rows
// }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
view?.findViewById<Toolbar>(R.id.toolbar)?.let { toolbar ->
toolbar.menu.removeItem(R.id.menu_item_transaction_filter)
transactionFilterMenuItem = toolbar.menu?.add(0, R.id.menu_item_transaction_filter, 1, R.string.filter)
transactionFilterMenuItem?.setIcon(R.drawable.baseline_payment_24)
transactionFilterMenuItem?.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM)
setTransactionFilterItemColor()
}
}
private fun setTransactionFilterItemColor() {
context?.let {
val userConfig = UserConfig.getConfiguration(getRealm())
val color = if (userConfig.transactionTypeIds.isNotEmpty()) R.color.red else R.color.white
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
this.transactionFilterMenuItem?.iconTintList = ColorStateList.valueOf(it.getColor(color))
}
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.menu_item_transaction_filter -> {
showTransactionFilter()
}
}
return super.onOptionsItemSelected(item)
}
private fun showTransactionFilter() {
context?.let {
TransactionFilterActivity.newInstance(it)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
@ -130,18 +147,11 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
// Business
override fun asyncListenedEntityChange(realm: Realm) {
if (isAdded) { // Fixes: java.lang.IllegalStateException Fragment StatisticsFragment{9d3e5ec} not attached to a context.
launchStatComputation()
}
// val report = createSessionGroupsAndStartCompute(realm)
// tableReportFragment.report = report
//
// GlobalScope.launch(Dispatchers.Main) {
// tableReportFragment.showResults()
// }
setTransactionFilterItemColor()
}
/**
@ -149,7 +159,7 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
*/
private fun launchStatComputation() {
GlobalScope.launch(coroutineContext) {
CoroutineScope(coroutineContext).launch {
val async = GlobalScope.async {
val s = Date()
@ -238,6 +248,8 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
computedStats.addAll(tStats)
options.stats = computedStats
options.includedTransactions = UserConfig.getConfiguration(realm).transactionTypes(realm)
return Calculator.computeGroups(realm, listOf(allSessionGroup, cgSessionGroup, tSessionGroup), options)
}

@ -27,8 +27,7 @@ import net.pokeranalytics.android.util.Preferences
* - Listen for INTENT_FILTER_UPDATE_FILTER_UI
* -
*/
open class FilterableFragment : RealmFragment(),
FilterHandler {
open class FilterableFragment : RealmFragment(), FilterHandler {
override var currentFilterable: FilterableType = FilterableType.ALL
set(value) {
@ -83,7 +82,7 @@ open class FilterableFragment : RealmFragment(),
super.onCreateOptionsMenu(menu, inflater)
view?.findViewById<Toolbar>(R.id.toolbar)?.let { toolbar ->
toolbar.menu.removeItem(R.id.menu_item_filter)
filterMenuItem = toolbar.menu?.add(0, R.id.menu_item_filter, 0, R.string.filter)
filterMenuItem = toolbar.menu?.add(0, R.id.menu_item_filter, 10, R.string.filter)
filterMenuItem?.setIcon(R.drawable.ic_outline_filter_list)
filterMenuItem?.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM)
}

@ -76,18 +76,6 @@ open class RealmFragment : BaseFragment() {
this.observedRealmResults.add(results)
}
// fun listenRealmChanges(listener: RealmAsyncListener, clazz: Class<out RealmModel>) {
//
// this.changeListener = listener
//
// this.realmResults = this.realm.where(clazz).findAllAsync()
// this.realmResults?.addChangeListener { t, _ ->
// Timber.d("Realm changes: ${realmResults?.size}, $this")
// this.changeListener?.asyncListenedEntityChange(t.realm)
// }
//
// }
override fun onDestroyView() {
super.onDestroyView()

@ -34,7 +34,7 @@ class DealtHandsPerHourFragment : RealmFragment() {
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
menu.clear()
inflater.inflate(R.menu.toolbar_dealt_hands_per_hour, menu)
inflater.inflate(R.menu.toolbar_save, menu)
super.onCreateOptionsMenu(menu, inflater)
}

@ -0,0 +1,25 @@
package net.pokeranalytics.android.ui.modules.settings
import android.content.Context
import android.content.Intent
import android.os.Bundle
import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.activity.components.BaseActivity
class TransactionFilterActivity : BaseActivity() {
companion object {
fun newInstance(context: Context) {
val intent = Intent(context, TransactionFilterActivity::class.java)
context.startActivity(intent)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_transaction_filter)
}
}

@ -0,0 +1,132 @@
package net.pokeranalytics.android.ui.modules.settings
import android.content.Context
import android.os.Bundle
import android.view.*
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import io.realm.kotlin.where
import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentTransactionFilterBinding
import net.pokeranalytics.android.model.realm.TransactionType
import net.pokeranalytics.android.model.realm.UserConfig
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.fragment.components.RealmFragment
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
class TransactionFilterFragment : RealmFragment(), StaticRowRepresentableDataSource,
RowRepresentableDelegate {
private var _binding: FragmentTransactionFilterBinding? = null
private val binding get() = _binding!!
private lateinit var model: TransactionFilterViewModel
private lateinit var rowRepresentableAdapter: RowRepresentableAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
this.model = activity?.run {
ViewModelProvider(this).get(TransactionFilterViewModel::class.java)
} ?: throw Exception("Invalid Activity")
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentTransactionFilterBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initUI()
initData()
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
menu.clear()
inflater.inflate(R.menu.toolbar_save, menu)
super.onCreateOptionsMenu(menu, inflater)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.save -> save()
}
return true
}
private fun initUI() {
setDisplayHomeAsUpEnabled(true)
val viewManager = LinearLayoutManager(requireContext())
this.binding.recyclerView.apply {
setHasFixedSize(true)
layoutManager = viewManager
}
this.rowRepresentableAdapter = RowRepresentableAdapter(this, this)
this.binding.recyclerView.adapter = rowRepresentableAdapter
}
private fun initData() {
val transactionTypes = getRealm().where<TransactionType>()
.notEqualTo("kind", TransactionType.Value.DEPOSIT.uniqueIdentifier)
.notEqualTo("kind", TransactionType.Value.WITHDRAWAL.uniqueIdentifier)
.notEqualTo("kind", TransactionType.Value.TRANSFER.uniqueIdentifier)
.notEqualTo("kind", TransactionType.Value.STACKING_INCOMING.uniqueIdentifier)
.notEqualTo("kind", TransactionType.Value.STACKING_OUTGOING.uniqueIdentifier)
.sort("name")
.findAll()
this.model.transactionTypes = transactionTypes
val userConfig = UserConfig.getConfiguration(this.getRealm())
this.model.selectedTransactionTypes = userConfig.transactionTypes(getRealm()).toMutableSet()
}
private fun save() {
getRealm().executeTransaction { realm ->
val userConfig = UserConfig.getConfiguration(realm)
userConfig.setTransactionTypeIds(this.model.selectedTransactionTypes)
realm.copyToRealmOrUpdate(userConfig)
}
this.activity?.finish()
}
override fun adapterRows(): List<RowRepresentable> {
return this.model.transactionTypes.map { TransactionTypeSwitchRow(it) }
}
override fun boolForRow(row: RowRepresentable): Boolean {
val transactionTypeRow = row as TransactionTypeSwitchRow
return this.model.selectedTransactionTypes.contains(transactionTypeRow.transactionType)
}
override fun onRowValueChanged(value: Any?, row: RowRepresentable) {
val isChecked = value as Boolean
val transactionTypeRow = row as TransactionTypeSwitchRow
this.model.selectTransactionType(transactionTypeRow.transactionType, isChecked)
}
}
class TransactionTypeSwitchRow(val transactionType: TransactionType) : RowRepresentable {
override fun getDisplayName(context: Context): String {
return transactionType.name
}
override val viewType: Int = RowViewType.TITLE_SWITCH.identifier
}

@ -0,0 +1,19 @@
package net.pokeranalytics.android.ui.modules.settings
import androidx.lifecycle.ViewModel
import net.pokeranalytics.android.model.realm.TransactionType
class TransactionFilterViewModel : ViewModel() {
lateinit var transactionTypes: List<TransactionType>
var selectedTransactionTypes: MutableSet<TransactionType> = mutableSetOf()
fun selectTransactionType(transactionType: TransactionType, selected: Boolean) {
when(selected) {
true -> this.selectedTransactionTypes.add(transactionType)
false -> this.selectedTransactionTypes.remove(transactionType)
}
}
}

@ -4,3 +4,4 @@ const val NULL_TEXT: String = "--"
const val RANDOM_PLAYER: String = ""
const val FFMPEG_DESCRIPTOR_FILE = "descriptor.txt"
const val BLIND_SEPARATOR: String = "/"
const val UUID_SEPARATOR: String = ","

@ -47,7 +47,7 @@ class Preferences {
PATCH_NEGATIVE_LIMITS("negativeLimits"),
PATCH_STAKES("patchStakes"),
CLEAN_BLINDS_FILTERS("deleteBlindsFilters"),
SHOW_INAPP_BADGES("showInAppBadges"),
SHOW_IN_APP_BADGES("showInAppBadges"),
LAST_CALENDAR_BADGE_DATE("lastCalendarBadgeDate")
}
@ -101,6 +101,18 @@ class Preferences {
companion object {
fun setStringSet(key: PreferenceKey, value: MutableSet<String>, context: Context) {
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
val editor = preferences.edit()
editor.putStringSet(key.identifier, value)
editor.apply()
}
fun getStringSet(key: Keys, context: Context): MutableSet<String>? {
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
return preferences.getStringSet(key.identifier, null)
}
fun setString(key: PreferenceKey, value: String, context: Context) {
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
val editor = preferences.edit()
@ -232,14 +244,6 @@ class Preferences {
}
}
// fun executeOnceInThread(key: Keys, context: Context, executable: () -> Unit) {
//
// if (!getBoolean(key, context)) {
// Thread { executable.invoke() }
// setBoolean(key, true, context)
// }
// }
fun setResultCaptureType(bankroll: Bankroll, type: ResultCaptureType, context: Context) {
val key = "${Keys.BANKROLL_RESULT_CAPTURE_TYPE}${bankroll.id}"
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
@ -307,11 +311,11 @@ class Preferences {
}
fun showInAppBadges(context: Context): Boolean {
return getBoolean(Keys.SHOW_INAPP_BADGES, context, true)
return getBoolean(Keys.SHOW_IN_APP_BADGES, context, true)
}
fun setShowInAppBadges(context: Context, show: Boolean) {
setBoolean(Keys.SHOW_INAPP_BADGES, show, context)
setBoolean(Keys.SHOW_IN_APP_BADGES, show, context)
}
fun lastCalendarBadgeDate(context: Context): Long {

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M20,4L4,4c-1.11,0 -1.99,0.89 -1.99,2L2,18c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,6c0,-1.11 -0.89,-2 -2,-2zM20,18L4,18v-6h16v6zM20,8L4,8L4,6h16v2z"/>
</vector>

@ -0,0 +1,15 @@
<?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="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment"
android:name="net.pokeranalytics.android.ui.modules.settings.TransactionFilterFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="@layout/fragment_transaction_filter" />
</LinearLayout>

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
@ -25,33 +24,4 @@
</androidx.core.widget.NestedScrollView>
<!--<com.google.android.material.appbar.AppBarLayout-->
<!--android:id="@+id/appBar"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="128dp"-->
<!--android:theme="@style/PokerAnalyticsTheme.Toolbar.Session">-->
<!--<com.google.android.material.appbar.CollapsingToolbarLayout-->
<!--android:id="@+id/collapsingToolbar"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="match_parent"-->
<!--app:collapsedTitleTextAppearance="@style/PokerAnalyticsTheme.Toolbar.CollapsedTitleAppearance"-->
<!--app:contentScrim="?attr/colorPrimary"-->
<!--app:expandedTitleGravity="bottom"-->
<!--app:expandedTitleMarginStart="72dp"-->
<!--app:expandedTitleTextAppearance="@style/PokerAnalyticsTheme.Toolbar.ExpandedTitleAppearance"-->
<!--app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">-->
<!--<androidx.appcompat.widget.Toolbar-->
<!--android:id="@+id/toolbar"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="?attr/actionBarSize"-->
<!--app:layout_collapseMode="pin"-->
<!--app:titleTextColor="@color/white"-->
<!--app:title="@string/services" />-->
<!--</com.google.android.material.appbar.CollapsingToolbarLayout>-->
<!--</com.google.android.material.appbar.AppBarLayout>-->
</androidx.coordinatorlayout.widget.CoordinatorLayout>

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="128dp"
android:theme="@style/PokerAnalyticsTheme.Toolbar.Session"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsingToolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:collapsedTitleTextAppearance="@style/PokerAnalyticsTheme.Toolbar.CollapsedTitleAppearance"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleGravity="bottom"
app:expandedTitleMarginStart="72dp"
app:expandedTitleTextAppearance="@style/PokerAnalyticsTheme.Toolbar.ExpandedTitleAppearance"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:title="@string/transaction_filter"
app:titleTextColor="@color/white" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false" />
</FrameLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

@ -787,5 +787,6 @@
<string name="more_sign"><![CDATA[>]]></string>
<string name="less_or_equal_sign"><![CDATA[≤]]></string>
<string name="less_sign"><![CDATA[<]]></string>
<string name="transaction_filter">Filtre de transactions</string>
</resources>

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="menu_item_filter" type="id"/>
<item name="menu_item_transaction_filter" type="id"/>
</resources>

@ -831,5 +831,6 @@
<string name="less_or_equal_sign"><![CDATA[≤]]></string>
<string name="less_sign"><![CDATA[<]]></string>
<string name="empty_reports_screen">This screen will show where you perform the best when you\'ll have more data. You also can create custom reports using the top right button.</string>
<string name="transaction_filter">Transaction Filter</string>
</resources>

Loading…
Cancel
Save