threading
Laurent 3 years ago
parent 7c64408749
commit 897098499f
  1. 9
      app/build.gradle
  2. 1
      app/src/main/AndroidManifest.xml
  3. 42
      app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt
  4. 56
      app/src/main/java/net/pokeranalytics/android/RealmWriteService.kt
  5. 2
      app/src/main/java/net/pokeranalytics/android/calculus/Calculator.kt
  6. 2
      app/src/main/java/net/pokeranalytics/android/calculus/ComputableGroup.kt
  7. 31
      app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt
  8. 10
      app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReportManager.kt
  9. 19
      app/src/main/java/net/pokeranalytics/android/model/Criteria.kt
  10. 10
      app/src/main/java/net/pokeranalytics/android/model/filter/Query.kt
  11. 1
      app/src/main/java/net/pokeranalytics/android/model/realm/UserConfig.kt
  12. 3
      app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt
  13. 6
      app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt
  14. 22
      app/src/main/java/net/pokeranalytics/android/ui/activity/components/BaseActivity.kt
  15. 27
      app/src/main/java/net/pokeranalytics/android/ui/fragment/ImportFragment.kt
  16. 5
      app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt
  17. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt
  18. 3
      app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt
  19. 4
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt
  20. 49
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/RealmFragment.kt
  21. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/report/AbstractReportFragment.kt
  22. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/report/ProgressReportFragment.kt
  23. 2
      app/src/main/java/net/pokeranalytics/android/ui/helpers/AppReviewManager.kt
  24. 5
      app/src/main/java/net/pokeranalytics/android/ui/modules/bankroll/BankrollFragment.kt
  25. 144
      app/src/main/java/net/pokeranalytics/android/ui/modules/calendar/CalendarFragment.kt
  26. 2
      app/src/main/java/net/pokeranalytics/android/ui/modules/data/DataManagerFragment.kt
  27. 4
      app/src/main/java/net/pokeranalytics/android/ui/modules/data/EditableDataFragment.kt
  28. 29
      app/src/main/java/net/pokeranalytics/android/ui/modules/feed/FeedFragment.kt
  29. 2
      app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt
  30. 9
      app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt
  31. 1
      app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterHandler.kt
  32. 4
      app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersFragment.kt
  33. 2
      app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersListFragment.kt
  34. 2
      app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/editor/EditorFragment.kt
  35. 12
      app/src/main/java/net/pokeranalytics/android/ui/modules/session/SessionFragment.kt
  36. 2
      app/src/main/java/net/pokeranalytics/android/ui/modules/settings/DealtHandsPerHourFragment.kt
  37. 2
      app/src/main/java/net/pokeranalytics/android/ui/modules/settings/TransactionFilterFragment.kt
  38. 7
      app/src/main/java/net/pokeranalytics/android/ui/view/rows/FilterCategoryRow.kt
  39. 43
      app/src/main/java/net/pokeranalytics/android/ui/view/rows/FilterSectionRow.kt
  40. 10
      app/src/main/java/net/pokeranalytics/android/util/Global.kt
  41. 6
      build.gradle

@ -12,7 +12,7 @@ apply plugin: "kotlinx-serialization"
repositories { repositories {
maven { url 'https://jitpack.io' } // required for MPAndroidChart maven { url 'https://jitpack.io' } // required for MPAndroidChart
jcenter() // for kotlin serialization mavenCentral() // for kotlin serialization
} }
android { android {
@ -98,8 +98,8 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
// Kotlin // Kotlin
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.6' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0-native-mt'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.6" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0-native-mt"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
// implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0") // JVM dependency // implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0") // JVM dependency
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1" implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1"
@ -141,6 +141,9 @@ dependencies {
// ffmpeg for encoding video (HH export) // ffmpeg for encoding video (HH export)
implementation 'com.arthenica:ffmpeg-kit-min-gpl:4.4.LTS' implementation 'com.arthenica:ffmpeg-kit-min-gpl:4.4.LTS'
// https://mvnrepository.com/artifact/com.android.volley/volley
implementation 'com.android.volley:volley:1.2.1'
// Instrumented Tests // Instrumented Tests
androidTestImplementation 'androidx.test:core:1.3.0' androidTestImplementation 'androidx.test:core:1.3.0'
androidTestImplementation 'androidx.test:runner:1.3.0' androidTestImplementation 'androidx.test:runner:1.3.0'

@ -188,6 +188,7 @@
android:launchMode="singleTop"/> android:launchMode="singleTop"/>
<service android:name="net.pokeranalytics.android.ui.modules.handhistory.replayer.ReplayExportService" android:exported="false"/> <service android:name="net.pokeranalytics.android.ui.modules.handhistory.replayer.ReplayExportService" android:exported="false"/>
<service android:name="net.pokeranalytics.android.RealmWriteService" android:exported="false"/>
<meta-data <meta-data
android:name="preloaded_fonts" android:name="preloaded_fonts"

@ -1,8 +1,12 @@
package net.pokeranalytics.android package net.pokeranalytics.android
import android.app.Application import android.app.Application
import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Build import android.os.Build
import android.os.IBinder
import com.google.firebase.FirebaseApp import com.google.firebase.FirebaseApp
import io.realm.Realm import io.realm.Realm
import io.realm.RealmConfiguration import io.realm.RealmConfiguration
@ -11,6 +15,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import net.pokeranalytics.android.calculus.ReportWhistleBlower import net.pokeranalytics.android.calculus.ReportWhistleBlower
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.migrations.Patcher import net.pokeranalytics.android.model.migrations.Patcher
import net.pokeranalytics.android.model.migrations.PokerAnalyticsMigration import net.pokeranalytics.android.model.migrations.PokerAnalyticsMigration
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
@ -24,11 +29,16 @@ import net.pokeranalytics.android.util.billing.AppGuard
import timber.log.Timber import timber.log.Timber
import java.util.* import java.util.*
object AppState {
var isImporting = false
}
class PokerAnalyticsApplication : Application() { class PokerAnalyticsApplication : Application() {
var reportWhistleBlower: ReportWhistleBlower? = null var reportWhistleBlower: ReportWhistleBlower? = null
private var realmWriteService: RealmWriteService? = null
companion object { companion object {
fun timeSinceInstall(context: Context): Long { fun timeSinceInstall(context: Context): Long {
@ -60,6 +70,8 @@ class PokerAnalyticsApplication : Application() {
.build() .build()
Realm.setDefaultConfiguration(realmConfiguration) Realm.setDefaultConfiguration(realmConfiguration)
initRealmWriteService()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val locales = resources.configuration.locales val locales = resources.configuration.locales
CrashLogging.log("App onCreate. Locales = $locales") CrashLogging.log("App onCreate. Locales = $locales")
@ -81,7 +93,7 @@ class PokerAnalyticsApplication : Application() {
// Patch // Patch
Patcher.patchAll(this) Patcher.patchAll(this)
// Report // Reports
this.reportWhistleBlower = ReportWhistleBlower(this.applicationContext) this.reportWhistleBlower = ReportWhistleBlower(this.applicationContext)
SessionSetManager.configure() SessionSetManager.configure()
@ -91,6 +103,34 @@ class PokerAnalyticsApplication : Application() {
} }
/** Defines callbacks for service binding, passed to bindService() */
private val connection = object : ServiceConnection {
override fun onServiceDisconnected(name: ComponentName?) {
realmWriteService = null
}
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
val binder = service as RealmWriteService.LocalBinder
realmWriteService = binder.getService()
}
}
private fun initRealmWriteService() {
val intent = Intent(this, RealmWriteService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
override fun onTerminate() {
super.onTerminate()
unbindService(connection)
}
fun executeRealmAsyncTransaction(handler: (Realm) -> (Unit)) {
this.realmWriteService?.executeRealmAsyncTransaction(handler) ?: throw PAIllegalStateException("no realmWriteService")
}
/** /**
* Create fake sessions if we have less than 10 sessions * Create fake sessions if we have less than 10 sessions
*/ */

@ -0,0 +1,56 @@
package net.pokeranalytics.android
import android.app.Service
import android.content.Intent
import android.os.Binder
import android.os.IBinder
import io.realm.Realm
import timber.log.Timber
class RealmWriteService : Service() {
private lateinit var realm: Realm
private val binder = LocalBinder()
override fun onBind(intent: Intent?): IBinder {
return binder
}
inner class LocalBinder : Binder() {
fun getService(): RealmWriteService = this@RealmWriteService
}
override fun onCreate() {
super.onCreate()
this.realm = Realm.getDefaultInstance()
}
override fun onDestroy() {
super.onDestroy()
Timber.d(">>>> Service destroyed : realm close")
this.realm.close()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
}
fun executeRealmAsyncTransaction(handler: (Realm) -> (Unit)) {
Timber.d(">>>> Launch async transaction...")
this.realm.executeTransactionAsync({ asyncRealm ->
handler(asyncRealm)
Timber.d(">> handler done")
}, {
Timber.d(">> YEAAAAAAAAAAAH !!!")
this.realm.refresh()
}, {
Timber.d(">> NOOOOO error = $it")
})
}
}

@ -177,7 +177,7 @@ class Calculator {
val computableGroups: MutableList<ComputableGroup> = mutableListOf() val computableGroups: MutableList<ComputableGroup> = mutableListOf()
val combinations = options.criterias.combined() val combinations = options.criterias.combined(realm)
// Timber.d("Combinations: ${ combinations.map { it.defaultName }}") // Timber.d("Combinations: ${ combinations.map { it.defaultName }}")
for (comparatorQuery in combinations) { for (comparatorQuery in combinations) {

@ -53,6 +53,8 @@ class ComputableGroup(val query: Query, var displayedStats: List<Stat>? = null)
} }
} }
// Timber.d("QUERY = ${query.defaultName}")
val sortedField = if (sorted) "session.startDate" else null val sortedField = if (sorted) "session.startDate" else null
val computables = Filter.queryOn<ComputableResult>(realm, this.query, sortedField) val computables = Filter.queryOn<ComputableResult>(realm, this.query, sortedField)

@ -1,19 +1,24 @@
package net.pokeranalytics.android.calculus package net.pokeranalytics.android.calculus
import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.CountDownTimer import android.os.CountDownTimer
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import io.realm.Realm import io.realm.Realm
import io.realm.RealmQuery import io.realm.RealmQuery
import io.realm.RealmResults import io.realm.RealmResults
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import net.pokeranalytics.android.AppState
import net.pokeranalytics.android.calculus.optimalduration.CashGameOptimalDurationCalculator import net.pokeranalytics.android.calculus.optimalduration.CashGameOptimalDurationCalculator
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.LiveOnline import net.pokeranalytics.android.model.LiveOnline
import net.pokeranalytics.android.model.realm.* import net.pokeranalytics.android.model.realm.*
import net.pokeranalytics.android.ui.fragment.ImportBroadcast
import net.pokeranalytics.android.ui.view.rows.StaticReport import net.pokeranalytics.android.ui.view.rows.StaticReport
import net.pokeranalytics.android.util.Global
import net.pokeranalytics.android.util.extensions.formattedHourlyDuration import net.pokeranalytics.android.util.extensions.formattedHourlyDuration
import timber.log.Timber import timber.log.Timber
@ -33,10 +38,19 @@ class ReportWhistleBlower(var context: Context) {
private val listeners: MutableList<NewPerformanceListener> = mutableListOf() private val listeners: MutableList<NewPerformanceListener> = mutableListOf()
private var paused: Boolean = !Global.LAUNCH_ASYNC_LISTENERS
private var timer: CountDownTimer? = null private var timer: CountDownTimer? = null
private val startImportReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
pause()
}
}
private val endImportReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
resume()
}
}
init { init {
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
@ -57,6 +71,9 @@ class ReportWhistleBlower(var context: Context) {
} }
realm.close() realm.close()
LocalBroadcastManager.getInstance(context).registerReceiver(startImportReceiver, IntentFilter(ImportBroadcast.START.identifier))
LocalBroadcastManager.getInstance(context).registerReceiver(endImportReceiver, IntentFilter(ImportBroadcast.END.identifier))
} }
fun addListener(newPerformanceListener: NewPerformanceListener) { fun addListener(newPerformanceListener: NewPerformanceListener) {
@ -69,7 +86,7 @@ class ReportWhistleBlower(var context: Context) {
fun requestReportLaunch() { fun requestReportLaunch() {
if (paused) { if (AppState.isImporting) {
return return
} }
@ -103,14 +120,12 @@ class ReportWhistleBlower(var context: Context) {
/** /**
* Pauses the whistleblower, for example when importing data * Pauses the whistleblower, for example when importing data
*/ */
fun pause() { private fun pause() {
this.paused = true
this.currentTask?.cancel() this.currentTask?.cancel()
this.currentTask = null this.currentTask = null
} }
fun resume() { private fun resume() {
this.paused = false
this.requestReportLaunch() this.requestReportLaunch()
} }

@ -2,14 +2,14 @@ package net.pokeranalytics.android.calculus.bankroll
import io.realm.Realm import io.realm.Realm
import io.realm.RealmResults import io.realm.RealmResults
import kotlinx.coroutines.* import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.model.realm.Bankroll
import net.pokeranalytics.android.model.realm.ComputableResult import net.pokeranalytics.android.model.realm.ComputableResult
import net.pokeranalytics.android.model.realm.Transaction import net.pokeranalytics.android.model.realm.Transaction
import net.pokeranalytics.android.util.Global
import timber.log.Timber import timber.log.Timber
import java.util.*
import kotlin.coroutines.CoroutineContext
object BankrollReportManager { object BankrollReportManager {
@ -26,9 +26,7 @@ object BankrollReportManager {
bankrolls = realm.where(Bankroll::class.java).findAll() bankrolls = realm.where(Bankroll::class.java).findAll()
transactions = realm.where(Transaction::class.java).findAll() transactions = realm.where(Transaction::class.java).findAll()
if (Global.LAUNCH_ASYNC_LISTENERS) {
initializeListeners() initializeListeners()
}
realm.close() realm.close()
} }

@ -25,11 +25,12 @@ import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.util.enumerations.IntIdentifiable import net.pokeranalytics.android.util.enumerations.IntIdentifiable
import net.pokeranalytics.android.util.enumerations.IntSearchable import net.pokeranalytics.android.util.enumerations.IntSearchable
import net.pokeranalytics.android.util.extensions.findById import net.pokeranalytics.android.util.extensions.findById
import timber.log.Timber
fun List<Criteria>.combined(): List<Query> { fun List<Criteria>.combined(realm: Realm): List<Query> {
val comparatorList = ArrayList<List<Query>>() val comparatorList = ArrayList<List<Query>>()
this.forEach { criteria -> this.forEach { criteria ->
comparatorList.add(criteria.queries) comparatorList.add(criteria.queries(realm))
} }
return getCombinations(comparatorList) return getCombinations(comparatorList)
} }
@ -165,14 +166,11 @@ sealed class Criteria(override var uniqueIdentifier: Int) : IntIdentifiable, Row
data class ValueCustomFields(override var customFieldId: String) : ListCriteria(22), CustomFieldCriteria data class ValueCustomFields(override var customFieldId: String) : ListCriteria(22), CustomFieldCriteria
object Duration : ListCriteria(23) object Duration : ListCriteria(23)
val queries: List<Query> fun queries(realm: Realm): List<Query> {
get() {
return when (this) { return when (this) {
is AllMonthsUpToNow -> { is AllMonthsUpToNow -> {
val realm = Realm.getDefaultInstance()
val firstSession = realm.where<Session>().isNotNull("startDate").sort("startDate", Sort.ASCENDING).findFirst() val firstSession = realm.where<Session>().isNotNull("startDate").sort("startDate", Sort.ASCENDING).findFirst()
val lastSession = realm.where<Session>().isNotNull("startDate").sort("startDate", Sort.DESCENDING).findFirst() val lastSession = realm.where<Session>().isNotNull("startDate").sort("startDate", Sort.DESCENDING).findFirst()
realm.close()
val years: ArrayList<Query> = arrayListOf() val years: ArrayList<Query> = arrayListOf()
@ -200,13 +198,12 @@ sealed class Criteria(override var uniqueIdentifier: Int) : IntIdentifiable, Row
years years
} }
else -> { else -> {
return this.queryConditions return this.queryConditions(realm)
} }
} }
} }
val queryConditions: List<Query> fun queryConditions(realm: Realm): List<Query> {
get() {
return when (this) { return when (this) {
is Bankrolls -> comparison<Bankroll>() is Bankrolls -> comparison<Bankroll>()
is Games -> comparison<Game>() is Games -> comparison<Game>()
@ -221,7 +218,6 @@ sealed class Criteria(override var uniqueIdentifier: Int) : IntIdentifiable, Row
is TournamentFees -> comparison<QueryCondition.TournamentFee, Double>() is TournamentFees -> comparison<QueryCondition.TournamentFee, Double>()
is Years -> { is Years -> {
val years = arrayListOf<Query>() val years = arrayListOf<Query>()
val realm = Realm.getDefaultInstance()
val lastSession = realm.where<Session>().isNotNull("startDate").sort("startDate", Sort.DESCENDING).findFirst() val lastSession = realm.where<Session>().isNotNull("startDate").sort("startDate", Sort.DESCENDING).findFirst()
val yearNow = lastSession?.year ?: return years val yearNow = lastSession?.year ?: return years
@ -233,19 +229,16 @@ sealed class Criteria(override var uniqueIdentifier: Int) : IntIdentifiable, Row
years.add(Query(yearCondition)) years.add(Query(yearCondition))
} }
} }
realm.close()
years years
} }
is Stakes -> comparison<QueryCondition.AnyStake, String>() is Stakes -> comparison<QueryCondition.AnyStake, String>()
is ListCustomFields -> comparison<CustomFieldEntry>() is ListCustomFields -> comparison<CustomFieldEntry>()
is ValueCustomFields -> { is ValueCustomFields -> {
val realm = Realm.getDefaultInstance()
val queries = when (this.customFieldType(realm)) { val queries = when (this.customFieldType(realm)) {
CustomField.Type.AMOUNT.uniqueIdentifier -> comparison<QueryCondition.CustomFieldAmountQuery, Double >() CustomField.Type.AMOUNT.uniqueIdentifier -> comparison<QueryCondition.CustomFieldAmountQuery, Double >()
CustomField.Type.NUMBER.uniqueIdentifier -> comparison<QueryCondition.CustomFieldNumberQuery, Double >() CustomField.Type.NUMBER.uniqueIdentifier -> comparison<QueryCondition.CustomFieldNumberQuery, Double >()
else -> throw PokerAnalyticsException.ComparisonCriteriaUnhandled(this) else -> throw PokerAnalyticsException.ComparisonCriteriaUnhandled(this)
} }
realm.close()
queries queries
} }
is Duration -> { is Duration -> {

@ -73,16 +73,16 @@ class Query {
it is QueryCondition.EndedToTime it is QueryCondition.EndedToTime
} }
this.conditions.forEach { for (condition in this.conditions) {
realmQuery = when (it) { realmQuery = when (condition) {
is QueryCondition.StartedFromTime -> { is QueryCondition.StartedFromTime -> {
it.queryWith(realmQuery, queryToTime) condition.queryWith(realmQuery, queryToTime)
} }
is QueryCondition.EndedToTime -> { is QueryCondition.EndedToTime -> {
it.queryWith(realmQuery, queryFromTime) condition.queryWith(realmQuery, queryFromTime)
} }
else -> { else -> {
it.queryWith(realmQuery) condition.queryWith(realmQuery)
} }
} }
} }

@ -5,6 +5,7 @@ import io.realm.RealmObject
import io.realm.annotations.PrimaryKey import io.realm.annotations.PrimaryKey
import net.pokeranalytics.android.util.UUID_SEPARATOR import net.pokeranalytics.android.util.UUID_SEPARATOR
import net.pokeranalytics.android.util.extensions.findById import net.pokeranalytics.android.util.extensions.findById
import timber.log.Timber
import java.util.* import java.util.*
open class UserConfig : RealmObject() { open class UserConfig : RealmObject() {

@ -6,7 +6,6 @@ import io.realm.RealmResults
import net.pokeranalytics.android.exceptions.ModelException import net.pokeranalytics.android.exceptions.ModelException
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.SessionSet import net.pokeranalytics.android.model.realm.SessionSet
import net.pokeranalytics.android.util.Global
import net.pokeranalytics.android.util.extensions.findById import net.pokeranalytics.android.util.extensions.findById
import timber.log.Timber import timber.log.Timber
@ -33,7 +32,6 @@ object SessionSetManager {
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
this.sessions = realm.where(Session::class.java).findAllAsync() this.sessions = realm.where(Session::class.java).findAllAsync()
if (Global.LAUNCH_ASYNC_LISTENERS) {
this.sessions.addChangeListener { _, _ -> this.sessions.addChangeListener { _, _ ->
if (this.sessionIdsToProcess.isNotEmpty()) { if (this.sessionIdsToProcess.isNotEmpty()) {
realm.executeTransactionAsync { asyncRealm -> realm.executeTransactionAsync { asyncRealm ->
@ -41,7 +39,6 @@ object SessionSetManager {
} }
} }
} }
}
realm.close() realm.close()
} }

@ -17,7 +17,6 @@ import net.pokeranalytics.android.model.realm.Currency
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.activity.components.BaseActivity import net.pokeranalytics.android.ui.activity.components.BaseActivity
import net.pokeranalytics.android.ui.adapter.HomePagerAdapter import net.pokeranalytics.android.ui.adapter.HomePagerAdapter
import net.pokeranalytics.android.util.Global
import net.pokeranalytics.android.util.Preferences import net.pokeranalytics.android.util.Preferences
import net.pokeranalytics.android.util.billing.AppGuard import net.pokeranalytics.android.util.billing.AppGuard
import net.pokeranalytics.android.util.extensions.findAll import net.pokeranalytics.android.util.extensions.findAll
@ -115,17 +114,14 @@ class HomeActivity : BaseActivity(), NewPerformanceListener {
// observe currency changes // observe currency changes
this.currencies = realm.where(Currency::class.java).findAllAsync() this.currencies = realm.where(Currency::class.java).findAllAsync()
if (Global.LAUNCH_ASYNC_LISTENERS) {
this.currencies.addChangeListener { _, _ -> this.currencies.addChangeListener { _, _ ->
realm.executeTransactionAsync { asyncRealm -> getRealm().executeTransactionAsync { asyncRealm ->
asyncRealm.where(Currency::class.java).findAll().forEach { currency -> asyncRealm.where(Currency::class.java).findAll().forEach { currency ->
currency.refreshRelatedRatedValues() currency.refreshRelatedRatedValues()
} }
} }
} }
} }
}
/** /**
* Init UI * Init UI

@ -34,6 +34,7 @@ abstract class BaseActivity : AppCompatActivity() {
} }
private var realm: Realm? = null private var realm: Realm? = null
private var permissionCallback: ((granted: Boolean) -> Unit)? = null private var permissionCallback: ((granted: Boolean) -> Unit)? = null
private var permissionRequest: PermissionRequest? = null private var permissionRequest: PermissionRequest? = null
@ -86,7 +87,7 @@ abstract class BaseActivity : AppCompatActivity() {
override fun onBackPressed() { override fun onBackPressed() {
super.onBackPressed() super.onBackPressed()
AppReviewManager.showReviewManager(this) AppReviewManager.showReviewManagerIfNecessary(this)
} }
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
@ -136,10 +137,12 @@ abstract class BaseActivity : AppCompatActivity() {
fragmentTransaction.commit() fragmentTransaction.commit()
} }
/** /**
* Return the realm instance * Return the realm instance
*/ */
fun getRealm(): Realm { fun getRealm(): Realm {
// return this.realm
this.realm?.let { this.realm?.let {
return it return it
} ?: run { } ?: run {
@ -149,6 +152,23 @@ abstract class BaseActivity : AppCompatActivity() {
} }
} }
fun executeRealmAsyncTransaction(handler: (Realm) -> (Unit)) {
this.paApplication.executeRealmAsyncTransaction(handler)
// Timber.d(">>>> Launch async transaction")
//
// this.realm.executeTransactionAsync({ asyncRealm ->
// handler(asyncRealm)
// }, {
// Timber.d("YEAAAAAAAAAAAH !!!")
// this.realm.refresh()
// }, {
// Timber.d("NOOOOO error = $it")
// })
}
/** /**
* Return if the location permission has been granted by the user * Return if the location permission has been granted by the user
*/ */

@ -1,12 +1,15 @@
package net.pokeranalytics.android.ui.fragment package net.pokeranalytics.android.ui.fragment
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
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.* import kotlinx.coroutines.*
import net.pokeranalytics.android.AppState
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.databinding.FragmentImportBinding import net.pokeranalytics.android.databinding.FragmentImportBinding
import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.ui.fragment.components.RealmFragment
@ -17,6 +20,11 @@ import java.io.InputStream
import java.text.NumberFormat import java.text.NumberFormat
import java.util.* import java.util.*
enum class ImportBroadcast(var identifier: String) {
START("start-import"),
END("end-import")
}
class ImportFragment : RealmFragment(), ImportDelegate { class ImportFragment : RealmFragment(), ImportDelegate {
private lateinit var filePath: String private lateinit var filePath: String
@ -81,7 +89,10 @@ class ImportFragment : RealmFragment(), ImportDelegate {
private fun startImport() { private fun startImport() {
this.parentActivity?.paApplication?.reportWhistleBlower?.pause() AppState.isImporting = true
LocalBroadcastManager.getInstance(requireContext()).sendBroadcast(Intent(ImportBroadcast.START.identifier))
// this.parentActivity?.paApplication?.reportWhistleBlower?.pause()
this.importer = CSVImporter(inputStream) this.importer = CSVImporter(inputStream)
this.importer.delegate = this this.importer.delegate = this
@ -113,15 +124,6 @@ class ImportFragment : RealmFragment(), ImportDelegate {
snackBar.show() snackBar.show()
} }
// if (shouldDismissActivity) {
//
// activity?.let {
// it.setResult(ResultCode.IMPORT_UNRECOGNIZED_FORMAT.value)
// it.finish()
// }
//
// } else {
// }
importDidFinish() importDidFinish()
} }
@ -137,7 +139,10 @@ class ImportFragment : RealmFragment(), ImportDelegate {
} }
private fun end() { private fun end() {
this.parentActivity?.paApplication?.reportWhistleBlower?.resume()
AppState.isImporting = false
LocalBroadcastManager.getInstance(requireContext()).sendBroadcast(Intent(ImportBroadcast.END.identifier))
// this.parentActivity?.paApplication?.reportWhistleBlower?.resume()
activity?.finish() activity?.finish()
} }

@ -38,7 +38,6 @@ 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.rows.CustomizableRowRepresentable import net.pokeranalytics.android.ui.view.rows.CustomizableRowRepresentable
import net.pokeranalytics.android.ui.view.rows.StaticReport import net.pokeranalytics.android.ui.view.rows.StaticReport
import net.pokeranalytics.android.util.Global
import net.pokeranalytics.android.util.NULL_TEXT import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.Preferences import net.pokeranalytics.android.util.Preferences
import timber.log.Timber import timber.log.Timber
@ -154,14 +153,12 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc
this.reportSetups = getRealm().where(ReportSetup::class.java).sort("name").findAllAsync() this.reportSetups = getRealm().where(ReportSetup::class.java).sort("name").findAllAsync()
this.performances = getRealm().where(Performance::class.java).findAllAsync() this.performances = getRealm().where(Performance::class.java).findAllAsync()
if (Global.LAUNCH_ASYNC_LISTENERS) {
this.reportSetups.addChangeListener { _, _ -> this.reportSetups.addChangeListener { _, _ ->
this.updateRows() this.updateRows()
} }
this.performances.addChangeListener { _, _ -> this.performances.addChangeListener { _, _ ->
this.updateRows() this.updateRows()
} }
}
} }
@ -293,7 +290,7 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc
*/ */
private fun launchComputation(criteriaList: List<Criteria>, reportName: String, stat: Stat) { private fun launchComputation(criteriaList: List<Criteria>, reportName: String, stat: Stat) {
if (criteriaList.combined().size < 2) { if (criteriaList.combined(getRealm()).size < 2) {
Toast.makeText(context, R.string.less_then_2_values_for_display, Toast.LENGTH_LONG).show() Toast.makeText(context, R.string.less_then_2_values_for_display, Toast.LENGTH_LONG).show()
return return
} }

@ -185,7 +185,7 @@ class SettingsFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRep
Preferences.setCurrencyCode(currencyCode, requireContext()) Preferences.setCurrencyCode(currencyCode, requireContext())
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
realm.executeTransactionAsync { execRealm-> executeRealmAsyncTransaction { execRealm->
execRealm.where(Currency::class.java).findAll().forEach { currency -> execRealm.where(Currency::class.java).findAll().forEach { currency ->
currency.rate = (currency.rate ?: 1.0) * rate currency.rate = (currency.rate ?: 1.0) * rate
} }

@ -30,7 +30,6 @@ import net.pokeranalytics.android.ui.modules.filter.FilterActivityRequestCode
import net.pokeranalytics.android.ui.modules.filter.FilterableType import net.pokeranalytics.android.ui.modules.filter.FilterableType
import net.pokeranalytics.android.ui.modules.filter.FiltersActivity import net.pokeranalytics.android.ui.modules.filter.FiltersActivity
import net.pokeranalytics.android.ui.modules.settings.TransactionFilterActivity import net.pokeranalytics.android.ui.modules.settings.TransactionFilterActivity
import net.pokeranalytics.android.util.Global
import timber.log.Timber import timber.log.Timber
import java.util.* import java.util.*
@ -75,13 +74,11 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
this.currentFilterable = FilterableType.SESSION this.currentFilterable = FilterableType.SESSION
applyFilter() applyFilter()
if (Global.LAUNCH_ASYNC_LISTENERS) {
addRealmChangeListener(this, UserConfig::class.java) addRealmChangeListener(this, UserConfig::class.java)
addRealmChangeListener(this, ComputableResult::class.java) addRealmChangeListener(this, ComputableResult::class.java)
addRealmChangeListener(this, Transaction::class.java) addRealmChangeListener(this, Transaction::class.java)
addRealmChangeListener(this, SessionSet::class.java) addRealmChangeListener(this, SessionSet::class.java)
} }
}
private fun initUI() { private fun initUI() {
val fragmentTransaction = parentFragmentManager.beginTransaction() val fragmentTransaction = parentFragmentManager.beginTransaction()

@ -89,7 +89,7 @@ abstract class DeletableItemFragment : RealmFragment() {
deletedItem = getRealm().copyFromRealm(itemToDelete) deletedItem = getRealm().copyFromRealm(itemToDelete)
lastDeletedItemPosition = itemPosition lastDeletedItemPosition = itemPosition
getRealm().executeTransactionAsync { asyncRealm -> executeRealmAsyncTransaction { asyncRealm ->
val item = asyncRealm.findById(itemClass, itemId) as? Deletable val item = asyncRealm.findById(itemClass, itemId) as? Deletable
item?.let { item?.let {
item.deleteDependencies(asyncRealm) item.deleteDependencies(asyncRealm)
@ -123,7 +123,7 @@ abstract class DeletableItemFragment : RealmFragment() {
if (!itemHasBeenReInserted) { if (!itemHasBeenReInserted) {
itemHasBeenReInserted = true itemHasBeenReInserted = true
getRealm().executeTransactionAsync { realm -> executeRealmAsyncTransaction { realm ->
deletedItem?.let { deletedItem?.let {
val item = realm.copyToRealmOrUpdate(it) val item = realm.copyToRealmOrUpdate(it)
updateUIAfterUndoDeletion(item) updateUIAfterUndoDeletion(item)

@ -1,14 +1,20 @@
package net.pokeranalytics.android.ui.fragment.components package net.pokeranalytics.android.ui.fragment.components
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import io.realm.Realm import io.realm.Realm
import io.realm.RealmModel import io.realm.RealmModel
import io.realm.RealmResults import io.realm.RealmResults
import net.pokeranalytics.android.AppState
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.util.Global import net.pokeranalytics.android.ui.fragment.ImportBroadcast
interface RealmAsyncListener { interface RealmAsyncListener {
fun asyncListenedEntityChange(realm: Realm, clazz: Class<out RealmModel>) fun asyncListenedEntityChange(realm: Realm, clazz: Class<out RealmModel>)
@ -19,14 +25,21 @@ open class RealmFragment : BaseFragment() {
/** /**
* A realm instance * A realm instance
*/ */
private lateinit var realm: Realm // private lateinit var realm: Realm
/*** /***
* A listener to async updates * A listener to async updates
*/ */
private var changeListener: RealmAsyncListener? = null private var changeListener: RealmAsyncListener? = null
private var realmResults: RealmResults<out RealmModel>? = null private val endImportReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
sendRealmChange()
}
}
// private var realmResults: RealmResults<out RealmModel>? = null
/** /**
* A List of observed RealmResults * A List of observed RealmResults
@ -34,7 +47,8 @@ open class RealmFragment : BaseFragment() {
private var observedRealmResults: MutableList<RealmResults<*>> = mutableListOf() private var observedRealmResults: MutableList<RealmResults<*>> = mutableListOf()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
realm = Realm.getDefaultInstance() // realm = Realm.getDefaultInstance()
LocalBroadcastManager.getInstance(requireContext()).registerReceiver(endImportReceiver, IntentFilter(ImportBroadcast.END.identifier))
return super.onCreateView(inflater, container, savedInstanceState) return super.onCreateView(inflater, container, savedInstanceState)
} }
@ -42,7 +56,11 @@ open class RealmFragment : BaseFragment() {
* Get the realm instance * Get the realm instance
*/ */
fun getRealm(): Realm { fun getRealm(): Realm {
return this.realm return this.parentActivity?.getRealm() ?: throw PAIllegalStateException("parent activity missing")
}
fun executeRealmAsyncTransaction(handler: (Realm) -> (Unit)) {
this.parentActivity?.executeRealmAsyncTransaction(handler) ?: throw PAIllegalStateException("parent activity missing")
} }
fun addRealmChangeListener(listener: RealmAsyncListener, clazz: Class<out RealmModel>) { fun addRealmChangeListener(listener: RealmAsyncListener, clazz: Class<out RealmModel>) {
@ -52,23 +70,38 @@ open class RealmFragment : BaseFragment() {
} }
this.changeListener = listener this.changeListener = listener
val results = this.realm.where(clazz).findAllAsync() val results = getRealm().where(clazz).findAllAsync()
results.addChangeListener { res, _ -> results.addChangeListener { res, _ ->
// Timber.d("Realm changes: ${realmResults?.size}, $this") // Timber.d("Realm changes: ${realmResults?.size}, $this")
if (!AppState.isImporting) {
this.changeListener?.asyncListenedEntityChange(res.realm, clazz) this.changeListener?.asyncListenedEntityChange(res.realm, clazz)
} else {
this.changedClasses.add(clazz)
}
} }
this.observedRealmResults.add(results) this.observedRealmResults.add(results)
} }
private var changedClasses: MutableSet<Class<out RealmModel>> = mutableSetOf()
fun sendRealmChange() {
if (!AppState.isImporting) {
for (clazz in this.changedClasses) {
this.changeListener?.asyncListenedEntityChange(getRealm(), clazz)
}
this.changedClasses.clear()
}
}
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
LocalBroadcastManager.getInstance(requireContext()).unregisterReceiver(endImportReceiver)
this.observedRealmResults.forEach { this.observedRealmResults.forEach {
it.removeAllChangeListeners() it.removeAllChangeListeners()
} }
this.realm.close()
this.realmResults?.removeAllChangeListeners()
} }
/** /**

@ -125,7 +125,7 @@ abstract class AbstractReportFragment : DataManagerFragment() {
val firstSave = (this.model.primaryKey == null) val firstSave = (this.model.primaryKey == null)
getRealm().executeTransactionAsync { realm -> executeRealmAsyncTransaction { realm ->
if (firstSave) { if (firstSave) {
val options = this.selectedReport.options val options = this.selectedReport.options

@ -141,7 +141,7 @@ class ProgressReportFragment : AbstractReportFragment() {
when (aggregationType) { when (aggregationType) {
AggregationType.MONTH, AggregationType.YEAR -> { AggregationType.MONTH, AggregationType.YEAR -> {
if (aggregationType.criterias.combined().size < 2) { if (aggregationType.criterias.combined(getRealm()).size < 2) {
Toast.makeText(context, R.string.less_then_2_values_for_display, Toast.LENGTH_LONG).show() Toast.makeText(context, R.string.less_then_2_values_for_display, Toast.LENGTH_LONG).show()
return return
} }

@ -14,7 +14,7 @@ object AppReviewManager {
this.reviewRequested = true this.reviewRequested = true
} }
fun showReviewManager(activity: Activity) { fun showReviewManagerIfNecessary(activity: Activity) {
if (this.reviewRequested && this.shouldAskForReview(activity.baseContext)) { if (this.reviewRequested && this.shouldAskForReview(activity.baseContext)) {
this.reviewRequested = false this.reviewRequested = false

@ -33,11 +33,8 @@ import net.pokeranalytics.android.ui.view.rows.BankrollGraphRow
import net.pokeranalytics.android.ui.view.rows.BankrollMainRow import net.pokeranalytics.android.ui.view.rows.BankrollMainRow
import net.pokeranalytics.android.ui.view.rows.BankrollTotalRow import net.pokeranalytics.android.ui.view.rows.BankrollTotalRow
import net.pokeranalytics.android.ui.view.rows.CustomizableRowRepresentable import net.pokeranalytics.android.ui.view.rows.CustomizableRowRepresentable
import net.pokeranalytics.android.util.Global
import net.pokeranalytics.android.util.extensions.sorted import net.pokeranalytics.android.util.extensions.sorted
import timber.log.Timber import timber.log.Timber
import java.util.*
import kotlin.collections.ArrayList
interface BankrollRowRepresentable : RowRepresentable { interface BankrollRowRepresentable : RowRepresentable {
var bankrollId: String? var bankrollId: String?
@ -119,11 +116,9 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
private fun initData() { private fun initData() {
this.bankrolls = getRealm().sorted() this.bankrolls = getRealm().sorted()
if (Global.LAUNCH_ASYNC_LISTENERS) {
this.bankrolls.addChangeListener { _, _ -> this.bankrolls.addChangeListener { _, _ ->
this.createRowRepresentables() this.createRowRepresentables()
} }
}
this.createRowRepresentables() this.createRowRepresentables()
} }

@ -11,10 +11,13 @@ import io.realm.Realm
import io.realm.RealmModel import io.realm.RealmModel
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import net.pokeranalytics.android.AppState
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.Calculator import net.pokeranalytics.android.calculus.Calculator
import net.pokeranalytics.android.calculus.ComputedResults import net.pokeranalytics.android.calculus.ComputedResults
import net.pokeranalytics.android.calculus.Report
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.databinding.FragmentCalendarBinding import net.pokeranalytics.android.databinding.FragmentCalendarBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.exceptions.PAIllegalStateException
@ -35,13 +38,11 @@ import net.pokeranalytics.android.ui.view.CalendarTabs
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.rows.CustomizableRowRepresentable import net.pokeranalytics.android.ui.view.rows.CustomizableRowRepresentable
import net.pokeranalytics.android.util.Global
import net.pokeranalytics.android.util.extensions.* import net.pokeranalytics.android.util.extensions.*
import timber.log.Timber import timber.log.Timber
import java.util.* import java.util.*
import kotlin.collections.set import kotlin.collections.set
class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource, class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
RowRepresentableDelegate, RealmAsyncListener { RowRepresentableDelegate, RealmAsyncListener {
@ -85,6 +86,13 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
private var _binding: FragmentCalendarBinding? = null private var _binding: FragmentCalendarBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private val requiredStats: List<Stat > = listOf(
Stat.LOCATIONS_PLAYED,
Stat.LONGEST_STREAKS,
Stat.DAYS_PLAYED,
Stat.STANDARD_DEVIATION_HOURLY
)
// Life Cycle // Life Cycle
override fun onCreateView( override fun onCreateView(
@ -99,16 +107,14 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initData()
initUI() initUI()
initData()
if (Global.LAUNCH_ASYNC_LISTENERS) {
addRealmChangeListener(this, UserConfig::class.java) addRealmChangeListener(this, UserConfig::class.java)
addRealmChangeListener(this, ComputableResult::class.java) addRealmChangeListener(this, ComputableResult::class.java)
addRealmChangeListener(this, Transaction::class.java) addRealmChangeListener(this, Transaction::class.java)
addRealmChangeListener(this, SessionSet::class.java) addRealmChangeListener(this, SessionSet::class.java)
} }
}
private var transactionFilterMenuItem: MenuItem? = null private var transactionFilterMenuItem: MenuItem? = null
@ -162,14 +168,46 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
} }
private fun showDetails(computedResults: ComputedResults, title: String?) { private fun showDetails(computedResults: ComputedResults, title: String?) {
// start calculation with progress values
CoroutineScope(Dispatchers.Default).launch {
var report: Report? = null
val coroutine = async {
val realm = Realm.getDefaultInstance()
val options = Calculator.Options(
progressValues = Calculator.Options.ProgressValues.STANDARD,
stats = requiredStats,
query = computedResults.group.query,
includedTransactions = transactionTypes(realm)
)
report = Calculator.computeStats(realm, options = options)
realm.close()
}
coroutine.await()
launch(Dispatchers.Main) {
report?.results?.firstOrNull()?.let { cr ->
CalendarDetailsActivity.newInstance( CalendarDetailsActivity.newInstance(
requireContext(), requireContext(),
computedResults, cr,
sessionTypeCondition, sessionTypeCondition,
title title
) )
} }
}
}
}
override fun onRowSelected(position: Int, row: RowRepresentable, tag: Int) { override fun onRowSelected(position: Int, row: RowRepresentable, tag: Int) {
when (this.currentTimeFilter) { when (this.currentTimeFilter) {
@ -348,6 +386,10 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
CoroutineScope(Dispatchers.Default).launch { CoroutineScope(Dispatchers.Default).launch {
val async = async {
val s = Date()
Timber.d(">>> start...")
val realm = Realm.getDefaultInstance() val realm = Realm.getDefaultInstance()
realm.refresh() realm.refresh()
@ -355,12 +397,43 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
realm.close() realm.close()
val e = Date()
val duration = (e.time - s.time) / 1000.0
Timber.d(">>> computations took $duration seconds")
}
async.await()
launch(Dispatchers.Main) { launch(Dispatchers.Main) {
if (isAdded && !isDetached) {
displayData() displayData()
} }
} }
} }
// CoroutineScope(Dispatchers.Default).launch {
//
// val realm = Realm.getDefaultInstance()
// realm.refresh()
//
// launchStatComputation(realm)
//
// realm.close()
//
// launch(Dispatchers.Main) {
// displayData()
// }
// }
}
private fun transactionTypes(realm: Realm): List<TransactionType> {
var transactionTypes = listOf<TransactionType>()
UserConfig.getConfiguration(realm) { userConfig ->
transactionTypes = userConfig.transactionTypes(realm)
}
return transactionTypes
}
private fun launchStatComputation(realm: Realm) { private fun launchStatComputation(realm: Realm) {
Timber.d(">>> Launch calendar computations") Timber.d(">>> Launch calendar computations")
@ -368,26 +441,12 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
val calendar = Calendar.getInstance() val calendar = Calendar.getInstance()
calendar.time = Date().startOfMonth() calendar.time = Date().startOfMonth()
// val startDate = Date() val startDate = Date()
val requiredStats: List<Stat> = val transactionTypes = this.transactionTypes(realm)
listOf(
Stat.LOCATIONS_PLAYED,
Stat.LONGEST_STREAKS,
Stat.DAYS_PLAYED,
Stat.STANDARD_DEVIATION_HOURLY
)
var transactionTypes = listOf<TransactionType>()
UserConfig.getConfiguration(realm) { userConfig ->
transactionTypes = userConfig.transactionTypes(realm)
}
// val transactionTypes = UserConfig.getConfiguration(realm).transactionTypes(realm)
// All // All
val allOptions = Calculator.Options( val allOptions = Calculator.Options(
progressValues = Calculator.Options.ProgressValues.STANDARD,
stats = requiredStats, stats = requiredStats,
query = Query(this.sessionTypeCondition), query = Query(this.sessionTypeCondition),
includedTransactions = transactionTypes includedTransactions = transactionTypes
@ -397,7 +456,6 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
// Sliding Month [sm] // Sliding Month [sm]
val smOptions = Calculator.Options( val smOptions = Calculator.Options(
progressValues = Calculator.Options.ProgressValues.STANDARD,
stats = requiredStats, stats = requiredStats,
query = Query(this.slidingMonthQueryCondition, this.sessionTypeCondition), query = Query(this.slidingMonthQueryCondition, this.sessionTypeCondition),
includedTransactions = transactionTypes includedTransactions = transactionTypes
@ -410,23 +468,24 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
val monthlyReports: HashMap<Date, ComputedResults> = HashMap() val monthlyReports: HashMap<Date, ComputedResults> = HashMap()
val monthlyQueries = when (sessionTypeCondition) { val monthlyQueries = when (sessionTypeCondition) {
QueryCondition.IsCash -> listOf(Criteria.AllMonthsUpToNow, Criteria.Cash).combined() QueryCondition.IsCash -> listOf(Criteria.AllMonthsUpToNow, Criteria.Cash).combined(realm)
QueryCondition.IsTournament -> listOf(Criteria.AllMonthsUpToNow, Criteria.Tournament).combined() QueryCondition.IsTournament -> listOf(Criteria.AllMonthsUpToNow, Criteria.Tournament).combined(realm)
else -> listOf(Criteria.Years, Criteria.MonthsOfYear).combined() else -> listOf(Criteria.Years, Criteria.MonthsOfYear).combined(realm)
} }
monthlyQueries.forEach { query -> for (monthlyQuery in monthlyQueries) {
val options = Calculator.Options( val options = Calculator.Options(
progressValues = Calculator.Options.ProgressValues.STANDARD,
stats = requiredStats, stats = requiredStats,
query = query, query = monthlyQuery,
includedTransactions = transactionTypes includedTransactions = transactionTypes
) )
val report = Calculator.computeStats(realm, options = options) val report = Calculator.computeStats(realm, options = options)
report.results.forEach { computedResults ->
for (computedResults in report.results) {
if (!computedResults.isEmpty) { if (!computedResults.isEmpty) {
// Set date data // Set date data
query.conditions.forEach { condition ->
for (condition in monthlyQuery.conditions) {
when (condition) { when (condition) {
is QueryCondition.AnyYear -> calendar.set( is QueryCondition.AnyYear -> calendar.set(
Calendar.YEAR, Calendar.YEAR,
@ -443,11 +502,11 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
monthlyReports[calendar.time] = computedResults monthlyReports[calendar.time] = computedResults
} }
} }
} }
// Sliding Year [sm] // Sliding Year [sm]
val syOptions = Calculator.Options( val syOptions = Calculator.Options(
progressValues = Calculator.Options.ProgressValues.STANDARD,
stats = requiredStats, stats = requiredStats,
query = Query(this.slidingYearQueryCondition, this.sessionTypeCondition), query = Query(this.slidingYearQueryCondition, this.sessionTypeCondition),
includedTransactions = transactionTypes includedTransactions = transactionTypes
@ -462,14 +521,13 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
val yearlyReports: HashMap<Date, ComputedResults> = HashMap() val yearlyReports: HashMap<Date, ComputedResults> = HashMap()
val yearConditions = when (sessionTypeCondition) { val yearConditions = when (sessionTypeCondition) {
QueryCondition.IsCash -> listOf(Criteria.Years, Criteria.Cash).combined() QueryCondition.IsCash -> listOf(Criteria.Years, Criteria.Cash).combined(realm)
QueryCondition.IsTournament -> listOf(Criteria.Years, Criteria.Tournament).combined() QueryCondition.IsTournament -> listOf(Criteria.Years, Criteria.Tournament).combined(realm)
else -> listOf(Criteria.Years).combined() else -> listOf(Criteria.Years).combined(realm)
} }
yearConditions.forEach { query -> yearConditions.forEach { query ->
val options = Calculator.Options( val options = Calculator.Options(
progressValues = Calculator.Options.ProgressValues.STANDARD,
stats = requiredStats, stats = requiredStats,
query = query, query = query,
includedTransactions = transactionTypes includedTransactions = transactionTypes
@ -495,7 +553,7 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
sortedMonthlyReports = monthlyReports.toSortedMap(compareByDescending { it }) sortedMonthlyReports = monthlyReports.toSortedMap(compareByDescending { it })
sortedYearlyReports = yearlyReports.toSortedMap(compareByDescending { it }) sortedYearlyReports = yearlyReports.toSortedMap(compareByDescending { it })
// Timber.d("Computation: ${System.currentTimeMillis() - startDate.time}ms") Timber.d("Computation: ${System.currentTimeMillis() - startDate.time}ms")
} }
@ -505,9 +563,12 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
private fun displayData() { private fun displayData() {
// Timber.d("displayData") // Timber.d("displayData")
this.binding.progressBar.hideWithAnimation()
this.binding.recyclerView.showWithAnimation()
if (context == null) { return } // required because of launchAsyncStatComputation if (context == null) { return } // required because of launchAsyncStatComputation
// val startDate = Date() val startDate = Date()
datesForRows.clear() datesForRows.clear()
rows.clear() rows.clear()
@ -599,14 +660,11 @@ class CalendarFragment : RealmFragment(), StaticRowRepresentableDataSource,
} }
} }
// Timber.d("Display data: ${System.currentTimeMillis() - startDate.time}ms") Timber.d("Display data: ${System.currentTimeMillis() - startDate.time}ms")
// Timber.d("Rows: ${rows.size}") Timber.d("Rows: ${rows.size}")
this.calendarAdapter.notifyDataSetChanged() this.calendarAdapter.notifyDataSetChanged()
this.binding.progressBar.hideWithAnimation()
this.binding.recyclerView.showWithAnimation()
} }
override fun asyncListenedEntityChange(realm: Realm, clazz: Class<out RealmModel>) { override fun asyncListenedEntityChange(realm: Realm, clazz: Class<out RealmModel>) {

@ -108,7 +108,7 @@ open class DataManagerFragment : RealmFragment() {
when (status) { when (status) {
SaveValidityStatus.VALID -> { SaveValidityStatus.VALID -> {
this.getRealm().executeTransactionAsync { asyncRealm -> executeRealmAsyncTransaction { asyncRealm ->
asyncRealm.insertOrUpdate(savable) asyncRealm.insertOrUpdate(savable)
} }

@ -69,7 +69,8 @@ open class EditableDataFragment : DataManagerFragment(), RowRepresentableDelegat
(this.model.item as RowUpdatable).updateValue(value, row) (this.model.item as RowUpdatable).updateValue(value, row)
if (this.model.primaryKey != null) { if (this.model.primaryKey != null) {
getRealm().executeTransactionAsync { asyncRealm ->
executeRealmAsyncTransaction { asyncRealm ->
try { try {
asyncRealm.insertOrUpdate(this.model.item) asyncRealm.insertOrUpdate(this.model.item)
} catch (e: Exception) { } catch (e: Exception) {
@ -77,6 +78,7 @@ open class EditableDataFragment : DataManagerFragment(), RowRepresentableDelegat
throw e throw e
} }
} }
} }
rowRepresentableAdapter.refreshRow(row) rowRepresentableAdapter.refreshRow(row)

@ -12,10 +12,7 @@ import com.android.billingclient.api.Purchase
import com.google.android.material.badge.BadgeDrawable import com.google.android.material.badge.BadgeDrawable
import com.google.android.material.badge.BadgeUtils import com.google.android.material.badge.BadgeUtils
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import io.realm.Realm import io.realm.*
import io.realm.RealmModel
import io.realm.RealmResults
import io.realm.Sort
import io.realm.kotlin.where import io.realm.kotlin.where
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.api.BlogPostApi import net.pokeranalytics.android.api.BlogPostApi
@ -47,6 +44,7 @@ import net.pokeranalytics.android.util.billing.AppGuard
import net.pokeranalytics.android.util.billing.PurchaseListener import net.pokeranalytics.android.util.billing.PurchaseListener
import net.pokeranalytics.android.util.extensions.count import net.pokeranalytics.android.util.extensions.count
import net.pokeranalytics.android.util.extensions.findById import net.pokeranalytics.android.util.extensions.findById
import timber.log.Timber
import java.util.* import java.util.*
class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseListener, RealmAsyncListener { class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseListener, RealmAsyncListener {
@ -78,6 +76,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
private lateinit var realmTransactions: RealmResults<Transaction> private lateinit var realmTransactions: RealmResults<Transaction>
private lateinit var realmHandHistories: RealmResults<HandHistory> private lateinit var realmHandHistories: RealmResults<HandHistory>
// private lateinit var realmSessions: RealmResults<Session>
private var newSessionCreated: Boolean = false private var newSessionCreated: Boolean = false
private var adapterHasBeenSet: Boolean = false private var adapterHasBeenSet: Boolean = false
@ -88,8 +87,10 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
override fun asyncListenedEntityChange(realm: Realm, clazz: Class<out RealmModel>) { override fun asyncListenedEntityChange(realm: Realm, clazz: Class<out RealmModel>) {
Timber.d("asyncListenedEntityChange for $clazz")
when (clazz.kotlin) { when (clazz.kotlin) {
Session::class -> { Session::class -> {
Timber.d("WOWOWOOWOOWOWOWOWOWOWOWOWO")
this.sessionAdapter.refreshData() this.sessionAdapter.refreshData()
this.sessionAdapter.notifyDataSetChanged() this.sessionAdapter.notifyDataSetChanged()
} }
@ -148,12 +149,30 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
AppGuard.registerListener(this) AppGuard.registerListener(this)
// this.realmSessions = getRealm().where<Session>().findAllAsync()
// val listener = RealmChangeListener<RealmResults<Session>> {
// Timber.d("WOWOWOOWOOWOWOWOWOWOWOWOWO")
// sessionAdapter.refreshData()
// sessionAdapter.notifyDataSetChanged()
// }
// this.realmSessions.addChangeListener(listener)
// this.realmSessions.addChangeListener { t, changeSet ->
// Timber.d("WOWOWOOWOOWOWOWOWOWOWOWOWO")
// this.sessionAdapter.refreshData()
// this.sessionAdapter.notifyDataSetChanged()
// }
initUI() initUI()
initData() initData()
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
getRealm().refresh()
if (requestCode == RequestCode.FEED_MENU.value && resultCode == RESULT_OK && data != null) { if (requestCode == RequestCode.FEED_MENU.value && resultCode == RESULT_OK && data != null) {
when (data.getIntExtra(NewDataMenuActivity.IntentKey.CHOICE.keyName, -1)) { when (data.getIntExtra(NewDataMenuActivity.IntentKey.CHOICE.keyName, -1)) {
0 -> createNewSession(false) 0 -> createNewSession(false)
@ -489,7 +508,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
private fun deleteSelectedTransaction() { private fun deleteSelectedTransaction() {
selectedTransaction?.id?.let { id -> selectedTransaction?.id?.let { id ->
getRealm().executeTransactionAsync { asyncRealm -> executeRealmAsyncTransaction { asyncRealm ->
asyncRealm.findById<Transaction>(id)?.deleteFromRealm() asyncRealm.findById<Transaction>(id)?.deleteFromRealm()
} }
} }

@ -95,7 +95,7 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate {
val categoryRow = FilterCategoryRow.values()[category] val categoryRow = FilterCategoryRow.values()[category]
Timber.d("Category row = $categoryRow") Timber.d("Category row = $categoryRow")
val factory = FilterDetailsViewModelFactory(filter, categoryRow) val factory = FilterDetailsViewModelFactory(getRealm(), filter, categoryRow)
this.model = ViewModelProvider(this, factory).get(FilterDetailsViewModel::class.java) this.model = ViewModelProvider(this, factory).get(FilterDetailsViewModel::class.java)
} ?: throw PAIllegalStateException("Missing bundle") } ?: throw PAIllegalStateException("Missing bundle")

@ -3,6 +3,7 @@ package net.pokeranalytics.android.ui.modules.filter
import android.content.Context import android.content.Context
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import io.realm.Realm
import net.pokeranalytics.android.model.realm.Filter import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
@ -13,21 +14,21 @@ import net.pokeranalytics.android.ui.view.rows.FilterItemRow
import net.pokeranalytics.android.util.NULL_TEXT import net.pokeranalytics.android.util.NULL_TEXT
import timber.log.Timber import timber.log.Timber
class FilterDetailsViewModelFactory(var filter: Filter, private var categoryRow: FilterCategoryRow): ViewModelProvider.Factory { class FilterDetailsViewModelFactory(var realm: Realm, var filter: Filter, private var categoryRow: FilterCategoryRow): ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T { override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return FilterDetailsViewModel(categoryRow, filter) as T return FilterDetailsViewModel(realm, categoryRow, filter) as T
} }
} }
class FilterDetailsViewModel(categoryRow: FilterCategoryRow, var filter: Filter) : ViewModel(), StaticRowRepresentableDataSource { class FilterDetailsViewModel(var realm: Realm, categoryRow: FilterCategoryRow, var filter: Filter) : ViewModel(), StaticRowRepresentableDataSource {
private var rows: ArrayList<RowRepresentable> = ArrayList() private var rows: ArrayList<RowRepresentable> = ArrayList()
val selectedRows = ArrayList<FilterItemRow>() val selectedRows = ArrayList<FilterItemRow>()
init { init {
this.rows.addAll(categoryRow.filterElements) this.rows.addAll(categoryRow.filterElements(realm))
this.defineSelectedItems() this.defineSelectedItems()
} }

@ -9,6 +9,7 @@ import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.util.Preferences import net.pokeranalytics.android.util.Preferences
import net.pokeranalytics.android.util.enumerations.IntIdentifiable import net.pokeranalytics.android.util.enumerations.IntIdentifiable
import net.pokeranalytics.android.util.enumerations.IntSearchable import net.pokeranalytics.android.util.enumerations.IntSearchable
import timber.log.Timber
enum class FilterActivityRequestCode { enum class FilterActivityRequestCode {
SELECT_FILTER, SELECT_FILTER,

@ -217,7 +217,7 @@ open class FiltersFragment : RealmFragment(), RowRepresentableDelegate {
private fun save() { private fun save() {
val filter = this.model.currentFilter val filter = this.model.currentFilter
getRealm().executeTransactionAsync { asyncRealm -> executeRealmAsyncTransaction { asyncRealm ->
filter.name = filter.query.getName(requireContext()) filter.name = filter.query.getName(requireContext())
asyncRealm.insertOrUpdate(filter) asyncRealm.insertOrUpdate(filter)
} }
@ -233,7 +233,7 @@ open class FiltersFragment : RealmFragment(), RowRepresentableDelegate {
val filterCopy = this.model.filterCopy val filterCopy = this.model.filterCopy
val filterId = filterCopy?.id ?: "" val filterId = filterCopy?.id ?: ""
getRealm().executeTransactionAsync { realm -> executeRealmAsyncTransaction { realm ->
filterCopy?.let { filterCopy?.let {
realm.insertOrUpdate(it) realm.insertOrUpdate(it)
} }

@ -17,7 +17,7 @@ open class FiltersListFragment : DataListFragment() {
is Filter -> { is Filter -> {
row.updateValue(value, row) row.updateValue(value, row)
getRealm().executeTransactionAsync { asyncRealm -> executeRealmAsyncTransaction { asyncRealm ->
asyncRealm.insertOrUpdate(row) asyncRealm.insertOrUpdate(row)
} }
val index = this.model.items.indexOf(row) val index = this.model.items.indexOf(row)

@ -688,7 +688,7 @@ class EditorFragment : RealmFragment(), RowRepresentableDelegate, KeyboardListen
private fun deleteHand() { private fun deleteHand() {
val hhId = this.model.handHistory.id val hhId = this.model.handHistory.id
getRealm().executeTransactionAsync { asyncRealm -> executeRealmAsyncTransaction { asyncRealm ->
asyncRealm.findById<HandHistory>(hhId)?.deleteFromRealm() asyncRealm.findById<HandHistory>(hhId)?.deleteFromRealm()
} }

@ -11,6 +11,7 @@ import androidx.appcompat.content.res.AppCompatResources
import androidx.interpolator.view.animation.FastOutSlowInInterpolator import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import io.realm.Realm
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -62,7 +63,6 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
private var sessionMenu: Menu? = null private var sessionMenu: Menu? = null
private val oldRows: ArrayList<RowRepresentable> = ArrayList() private val oldRows: ArrayList<RowRepresentable> = ArrayList()
private var sessionHasBeenUserCustomized = false
private val handler: Handler = Handler() private val handler: Handler = Handler()
private val timer: Runnable = object : Runnable { private val timer: Runnable = object : Runnable {
@ -146,7 +146,6 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
binding.floatingActionButton.setOnClickListener { binding.floatingActionButton.setOnClickListener {
if (this.currentSession.isValidForSave()) { if (this.currentSession.isValidForSave()) {
sessionHasBeenUserCustomized = true
startPauseResumeSession() startPauseResumeSession()
} else { } else {
val builder = AlertDialog.Builder(requireContext()) val builder = AlertDialog.Builder(requireContext())
@ -198,10 +197,8 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
val session = copy.duplicate() val session = copy.duplicate()
currentSession = session currentSession = session
// } // }
sessionHasBeenUserCustomized = false
} else { // show existing session } else { // show existing session
currentSession = copy currentSession = copy
sessionHasBeenUserCustomized = true
} }
} ?: throw PAIllegalStateException("Session cannot be null here, session id = $sessionId") } ?: throw PAIllegalStateException("Session cannot be null here, session id = $sessionId")
@ -227,7 +224,6 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
} }
} }
this.sessionHasBeenUserCustomized = false
} }
} }
@ -273,7 +269,6 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
override fun onRowValueChanged(value: Any?, row: RowRepresentable) { override fun onRowValueChanged(value: Any?, row: RowRepresentable) {
Timber.d("value changed: $value, row: $row") Timber.d("value changed: $value, row: $row")
this.sessionHasBeenUserCustomized = true
updateSessionThenSaveAsynchronously { session -> updateSessionThenSaveAsynchronously { session ->
session.updateValue(value, row) session.updateValue(value, row)
@ -311,7 +306,7 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
return return
} }
getRealm().executeTransactionAsync { realm -> executeRealmAsyncTransaction { realm ->
val session = realm.copyToRealmOrUpdate(this.currentSession) val session = realm.copyToRealmOrUpdate(this.currentSession)
session.preCompute() session.preCompute()
@ -319,6 +314,7 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
realm.insertOrUpdate(customField) realm.insertOrUpdate(customField)
} }
} }
} }
/** /**
@ -539,7 +535,7 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepr
val bankrollId = this.currentSession.bankroll?.id val bankrollId = this.currentSession.bankroll?.id
val sessionId = this.currentSession.id val sessionId = this.currentSession.id
getRealm().executeTransactionAsync { asyncRealm -> executeRealmAsyncTransaction { asyncRealm ->
asyncRealm.findById<Session>(sessionId)?.delete() asyncRealm.findById<Session>(sessionId)?.delete()
} }

@ -58,7 +58,7 @@ class DealtHandsPerHourFragment : RealmFragment() {
private fun save() { private fun save() {
getRealm().executeTransactionAsync { realm -> executeRealmAsyncTransaction { realm ->
UserConfig.getConfiguration(realm) { userConfig -> UserConfig.getConfiguration(realm) { userConfig ->
this.liveValue.text.toString().toIntOrNull()?.let { liveDealtHandsPerHour -> this.liveValue.text.toString().toIntOrNull()?.let { liveDealtHandsPerHour ->

@ -97,7 +97,7 @@ class TransactionFilterFragment : RealmFragment(), StaticRowRepresentableDataSou
} }
private fun save() { private fun save() {
getRealm().executeTransactionAsync { asyncRealm -> executeRealmAsyncTransaction { asyncRealm ->
UserConfig.getConfiguration(asyncRealm) { userConfig -> UserConfig.getConfiguration(asyncRealm) { userConfig ->
userConfig.setTransactionTypeIds(this.model.selectedTransactionTypes) userConfig.setTransactionTypeIds(this.model.selectedTransactionTypes)
asyncRealm.insertOrUpdate(userConfig) asyncRealm.insertOrUpdate(userConfig)

@ -60,14 +60,13 @@ enum class FilterCategoryRow(override val resId: Int?, override val viewType: In
} }
} }
val filterElements: List<RowRepresentable> fun filterElements(realm: Realm): List<RowRepresentable> {
get() {
return filterSectionRows.flatMap { return filterSectionRows.flatMap {
val items = it.filterItems val items = it.filterItems(realm)
val list = mutableListOf<RowRepresentable>() val list = mutableListOf<RowRepresentable>()
if (items.isNotEmpty()) { if (items.isNotEmpty()) {
list.add(it) list.add(it)
list.addAll(it.filterItems) list.addAll(it.filterItems(realm))
} }
list list
} }

@ -1,6 +1,7 @@
package net.pokeranalytics.android.ui.view.rows package net.pokeranalytics.android.ui.view.rows
import android.content.Context import android.content.Context
import io.realm.Realm
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PokerAnalyticsException import net.pokeranalytics.android.exceptions.PokerAnalyticsException
import net.pokeranalytics.android.model.Criteria import net.pokeranalytics.android.model.Criteria
@ -71,9 +72,8 @@ sealed class FilterSectionRow(override val resId: Int?) : RowRepresentable {
val allowMultiSelection: Boolean val allowMultiSelection: Boolean
get() = (this.selectionType == SelectionType.MULTIPLE) get() = (this.selectionType == SelectionType.MULTIPLE)
val filterItems: List<FilterItemRow> fun filterItems(realm: Realm): List<FilterItemRow> {
get() { return this.queryConditions(realm).map {
return this.queryConditions.map {
rowWrapper(it, this@FilterSectionRow) rowWrapper(it, this@FilterSectionRow)
// it.toRowWrapper(this@FilterSectionRow) // it.toRowWrapper(this@FilterSectionRow)
} }
@ -101,15 +101,14 @@ sealed class FilterSectionRow(override val resId: Int?) : RowRepresentable {
} }
} }
private val queryConditions: List<QueryCondition> private fun queryConditions(realm: Realm): List<QueryCondition> {
get() {
return when (this@FilterSectionRow) { return when (this@FilterSectionRow) {
// General // General
CashOrTournament -> Criteria.SessionTypes.queryConditions.mapFirstCondition() CashOrTournament -> Criteria.SessionTypes.queryConditions(realm).mapFirstCondition()
LiveOrOnline -> Criteria.BankrollTypes.queryConditions.mapFirstCondition() LiveOrOnline -> Criteria.BankrollTypes.queryConditions(realm).mapFirstCondition()
Game -> Criteria.Games.queryConditions.mapFirstCondition() Game -> Criteria.Games.queryConditions(realm).mapFirstCondition()
LimitType -> Criteria.Limits.queryConditions.mapFirstCondition() LimitType -> Criteria.Limits.queryConditions(realm).mapFirstCondition()
TableSize -> Criteria.TableSizes.queryConditions.mapFirstCondition() TableSize -> Criteria.TableSizes.queryConditions(realm).mapFirstCondition()
// Date // Date
DynamicDate -> arrayListOf( DynamicDate -> arrayListOf(
QueryCondition.IsToday, QueryCondition.IsToday,
@ -120,9 +119,9 @@ sealed class FilterSectionRow(override val resId: Int?) : RowRepresentable {
QueryCondition.DuringThisYear QueryCondition.DuringThisYear
) )
WeekdayOrWeekend -> arrayListOf(QueryCondition.IsWeekDay, QueryCondition.IsWeekEnd) WeekdayOrWeekend -> arrayListOf(QueryCondition.IsWeekDay, QueryCondition.IsWeekEnd)
Year -> Criteria.Years.queryConditions.mapFirstCondition() Year -> Criteria.Years.queryConditions(realm).mapFirstCondition()
DayOfWeek -> Criteria.DaysOfWeek.queryConditions.mapFirstCondition() DayOfWeek -> Criteria.DaysOfWeek.queryConditions(realm).mapFirstCondition()
MonthOfYear -> Criteria.MonthsOfYear.queryConditions.mapFirstCondition() MonthOfYear -> Criteria.MonthsOfYear.queryConditions(realm).mapFirstCondition()
// Duration // Duration
SessionDuration -> QueryCondition.moreEqualOrLessEqual<QueryCondition.Duration>() SessionDuration -> QueryCondition.moreEqualOrLessEqual<QueryCondition.Duration>()
@ -135,20 +134,20 @@ sealed class FilterSectionRow(override val resId: Int?) : RowRepresentable {
//Sessions -> arrayListOf(QueryCondition.LastGame(), QueryCondition.LastSession()) //Sessions -> arrayListOf(QueryCondition.LastGame(), QueryCondition.LastSession())
// Cash // Cash
Stakes -> Criteria.Stakes.queryConditions.mapFirstCondition() Stakes -> Criteria.Stakes.queryConditions(realm).mapFirstCondition()
// CashRebuyCount -> QueryCondition.moreOrLess<QueryCondition.Rebuy>() // CashRebuyCount -> QueryCondition.moreOrLess<QueryCondition.Rebuy>()
// Tournament // Tournament
TournamentType -> Criteria.TournamentTypes.queryConditions.mapFirstCondition() TournamentType -> Criteria.TournamentTypes.queryConditions(realm).mapFirstCondition()
// CompletionPercentage -> arrayListOf() // CompletionPercentage -> arrayListOf()
TournamentFinalPosition -> QueryCondition.moreEqualOrLessEqual<QueryCondition.TournamentFinalPosition>() TournamentFinalPosition -> QueryCondition.moreEqualOrLessEqual<QueryCondition.TournamentFinalPosition>()
TournamentNumberOfPlayer -> QueryCondition.moreEqualOrLessEqual<QueryCondition.TournamentNumberOfPlayer>() TournamentNumberOfPlayer -> QueryCondition.moreEqualOrLessEqual<QueryCondition.TournamentNumberOfPlayer>()
TournamentEntryFee -> Criteria.TournamentFees.queryConditions.mapFirstCondition() TournamentEntryFee -> Criteria.TournamentFees.queryConditions(realm).mapFirstCondition()
TournamentName -> Criteria.TournamentNames.queryConditions.mapFirstCondition() TournamentName -> Criteria.TournamentNames.queryConditions(realm).mapFirstCondition()
TournamentFeature -> Criteria.TournamentFeatures.queryConditions.mapFirstCondition() TournamentFeature -> Criteria.TournamentFeatures.queryConditions(realm).mapFirstCondition()
Location -> Criteria.Locations.queryConditions.mapFirstCondition() Location -> Criteria.Locations.queryConditions(realm).mapFirstCondition()
Bankroll -> Criteria.Bankrolls.queryConditions.mapFirstCondition() Bankroll -> Criteria.Bankrolls.queryConditions(realm).mapFirstCondition()
MultiTabling -> QueryCondition.moreEqualOrLessEqual<QueryCondition.NumberOfTable>() MultiTabling -> QueryCondition.moreEqualOrLessEqual<QueryCondition.NumberOfTable>()
//NumberOfPlayers -> QueryCondition.moreOrLess<QueryCondition.TournamentNumberOfPlayer>() //NumberOfPlayers -> QueryCondition.moreOrLess<QueryCondition.TournamentNumberOfPlayer>()
NumberOfRebuy -> QueryCondition.moreEqualOrLessEqual<QueryCondition.NumberOfRebuy>() NumberOfRebuy -> QueryCondition.moreEqualOrLessEqual<QueryCondition.NumberOfRebuy>()
@ -158,12 +157,12 @@ sealed class FilterSectionRow(override val resId: Int?) : RowRepresentable {
addAll(QueryCondition.moreEqualOrLessEqual<QueryCondition.NetAmountWon>()) addAll(QueryCondition.moreEqualOrLessEqual<QueryCondition.NetAmountWon>())
addAll(QueryCondition.moreEqualOrLessEqual<QueryCondition.NetAmountLost>()) addAll(QueryCondition.moreEqualOrLessEqual<QueryCondition.NetAmountLost>())
} }
TransactionType -> Criteria.TransactionTypes.queryConditions.mapFirstCondition() TransactionType -> Criteria.TransactionTypes.queryConditions(realm).mapFirstCondition()
is CustomField -> { is CustomField -> {
val cf = this@FilterSectionRow.customField val cf = this@FilterSectionRow.customField
when { when {
cf.isListType -> { cf.isListType -> {
Criteria.ListCustomFields(cf.id).queryConditions.mapFirstCondition() Criteria.ListCustomFields(cf.id).queryConditions(realm).mapFirstCondition()
} }
cf.isAmountType -> { cf.isAmountType -> {
QueryCondition.moreEqualOrLessEqual<QueryCondition.CustomFieldAmountQuery>().apply { QueryCondition.moreEqualOrLessEqual<QueryCondition.CustomFieldAmountQuery>().apply {

@ -6,8 +6,8 @@ const val FFMPEG_DESCRIPTOR_FILE = "descriptor.txt"
const val BLIND_SEPARATOR: String = "/" const val BLIND_SEPARATOR: String = "/"
const val UUID_SEPARATOR: String = "," const val UUID_SEPARATOR: String = ","
class Global { //class Global {
companion object { // companion object {
const val LAUNCH_ASYNC_LISTENERS = false // const val LAUNCH_ASYNC_LISTENERS = false
} // }
} //}

@ -4,12 +4,12 @@ buildscript {
ext.kotlin_version = '1.7.21' ext.kotlin_version = '1.7.21'
repositories { repositories {
google() google()
jcenter() mavenCentral()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.2.2' classpath 'com.android.tools.build:gradle:4.2.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'io.realm:realm-gradle-plugin:10.3.1' classpath 'io.realm:realm-gradle-plugin:10.13.0'
// crashlytics // crashlytics
classpath 'com.google.gms:google-services:4.3.4' classpath 'com.google.gms:google-services:4.3.4'
@ -24,7 +24,7 @@ buildscript {
allprojects { allprojects {
repositories { repositories {
google() google()
jcenter() mavenCentral()
} }
} }

Loading…
Cancel
Save