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. 12
      app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReportManager.kt
  9. 21
      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. 11
      app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt
  13. 12
      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. 15
      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. 11
      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. 51
      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. 9
      app/src/main/java/net/pokeranalytics/android/ui/modules/bankroll/BankrollFragment.kt
  25. 172
      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 {
maven { url 'https://jitpack.io' } // required for MPAndroidChart
jcenter() // for kotlin serialization
mavenCentral() // for kotlin serialization
}
android {
@ -98,8 +98,8 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// Kotlin
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.6'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.6"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0-native-mt'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0-native-mt"
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-json:1.4.1"
@ -141,6 +141,9 @@ dependencies {
// ffmpeg for encoding video (HH export)
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
androidTestImplementation 'androidx.test:core:1.3.0'
androidTestImplementation 'androidx.test:runner:1.3.0'

@ -188,6 +188,7 @@
android:launchMode="singleTop"/>
<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
android:name="preloaded_fonts"

@ -1,8 +1,12 @@
package net.pokeranalytics.android
import android.app.Application
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Build
import android.os.IBinder
import com.google.firebase.FirebaseApp
import io.realm.Realm
import io.realm.RealmConfiguration
@ -11,6 +15,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
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.PokerAnalyticsMigration
import net.pokeranalytics.android.model.realm.Session
@ -24,11 +29,16 @@ import net.pokeranalytics.android.util.billing.AppGuard
import timber.log.Timber
import java.util.*
object AppState {
var isImporting = false
}
class PokerAnalyticsApplication : Application() {
var reportWhistleBlower: ReportWhistleBlower? = null
private var realmWriteService: RealmWriteService? = null
companion object {
fun timeSinceInstall(context: Context): Long {
@ -60,6 +70,8 @@ class PokerAnalyticsApplication : Application() {
.build()
Realm.setDefaultConfiguration(realmConfiguration)
initRealmWriteService()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val locales = resources.configuration.locales
CrashLogging.log("App onCreate. Locales = $locales")
@ -81,7 +93,7 @@ class PokerAnalyticsApplication : Application() {
// Patch
Patcher.patchAll(this)
// Report
// Reports
this.reportWhistleBlower = ReportWhistleBlower(this.applicationContext)
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
*/

@ -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 combinations = options.criterias.combined()
val combinations = options.criterias.combined(realm)
// Timber.d("Combinations: ${ combinations.map { it.defaultName }}")
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 computables = Filter.queryOn<ComputableResult>(realm, this.query, sortedField)

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

@ -2,14 +2,14 @@ package net.pokeranalytics.android.calculus.bankroll
import io.realm.Realm
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.ComputableResult
import net.pokeranalytics.android.model.realm.Transaction
import net.pokeranalytics.android.util.Global
import timber.log.Timber
import java.util.*
import kotlin.coroutines.CoroutineContext
object BankrollReportManager {
@ -26,9 +26,7 @@ object BankrollReportManager {
bankrolls = realm.where(Bankroll::class.java).findAll()
transactions = realm.where(Transaction::class.java).findAll()
if (Global.LAUNCH_ASYNC_LISTENERS) {
initializeListeners()
}
initializeListeners()
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.IntSearchable
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>>()
this.forEach { criteria ->
comparatorList.add(criteria.queries)
comparatorList.add(criteria.queries(realm))
}
return getCombinations(comparatorList)
}
@ -64,7 +65,7 @@ sealed class Criteria(override var uniqueIdentifier: Int) : IntIdentifiable, Row
inline fun <reified T : NameManageable> comparison(): List<Query> {
if (this is ListCustomFields) {
val objects = mutableListOf<QueryCondition.CustomFieldListQuery>()
val realm = Realm.getDefaultInstance()
val realm = Realm.getDefaultInstance()
realm.findById(CustomField::class.java, this.customFieldId)?.entries?.forEach {
objects.add(QueryCondition.CustomFieldListQuery(it))
}
@ -165,14 +166,11 @@ sealed class Criteria(override var uniqueIdentifier: Int) : IntIdentifiable, Row
data class ValueCustomFields(override var customFieldId: String) : ListCriteria(22), CustomFieldCriteria
object Duration : ListCriteria(23)
val queries: List<Query>
get() {
fun queries(realm: Realm): List<Query> {
return when (this) {
is AllMonthsUpToNow -> {
val realm = Realm.getDefaultInstance()
val firstSession = realm.where<Session>().isNotNull("startDate").sort("startDate", Sort.ASCENDING).findFirst()
val lastSession = realm.where<Session>().isNotNull("startDate").sort("startDate", Sort.DESCENDING).findFirst()
realm.close()
val years: ArrayList<Query> = arrayListOf()
@ -200,13 +198,12 @@ sealed class Criteria(override var uniqueIdentifier: Int) : IntIdentifiable, Row
years
}
else -> {
return this.queryConditions
return this.queryConditions(realm)
}
}
}
val queryConditions: List<Query>
get() {
fun queryConditions(realm: Realm): List<Query> {
return when (this) {
is Bankrolls -> comparison<Bankroll>()
is Games -> comparison<Game>()
@ -221,7 +218,6 @@ sealed class Criteria(override var uniqueIdentifier: Int) : IntIdentifiable, Row
is TournamentFees -> comparison<QueryCondition.TournamentFee, Double>()
is Years -> {
val years = arrayListOf<Query>()
val realm = Realm.getDefaultInstance()
val lastSession = realm.where<Session>().isNotNull("startDate").sort("startDate", Sort.DESCENDING).findFirst()
val yearNow = lastSession?.year ?: return years
@ -233,19 +229,16 @@ sealed class Criteria(override var uniqueIdentifier: Int) : IntIdentifiable, Row
years.add(Query(yearCondition))
}
}
realm.close()
years
}
is Stakes -> comparison<QueryCondition.AnyStake, String>()
is ListCustomFields -> comparison<CustomFieldEntry>()
is ValueCustomFields -> {
val realm = Realm.getDefaultInstance()
val queries = when (this.customFieldType(realm)) {
CustomField.Type.AMOUNT.uniqueIdentifier -> comparison<QueryCondition.CustomFieldAmountQuery, Double >()
CustomField.Type.NUMBER.uniqueIdentifier -> comparison<QueryCondition.CustomFieldNumberQuery, Double >()
else -> throw PokerAnalyticsException.ComparisonCriteriaUnhandled(this)
}
realm.close()
queries
}
is Duration -> {

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

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

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

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

@ -34,6 +34,7 @@ abstract class BaseActivity : AppCompatActivity() {
}
private var realm: Realm? = null
private var permissionCallback: ((granted: Boolean) -> Unit)? = null
private var permissionRequest: PermissionRequest? = null
@ -86,7 +87,7 @@ abstract class BaseActivity : AppCompatActivity() {
override fun onBackPressed() {
super.onBackPressed()
AppReviewManager.showReviewManager(this)
AppReviewManager.showReviewManagerIfNecessary(this)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
@ -136,10 +137,12 @@ abstract class BaseActivity : AppCompatActivity() {
fragmentTransaction.commit()
}
/**
* Return the realm instance
*/
fun getRealm(): Realm {
// return this.realm
this.realm?.let {
return it
} ?: 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
*/

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

@ -38,7 +38,6 @@ import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.rows.CustomizableRowRepresentable
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.Preferences
import timber.log.Timber
@ -154,13 +153,11 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc
this.reportSetups = getRealm().where(ReportSetup::class.java).sort("name").findAllAsync()
this.performances = getRealm().where(Performance::class.java).findAllAsync()
if (Global.LAUNCH_ASYNC_LISTENERS) {
this.reportSetups.addChangeListener { _, _ ->
this.updateRows()
}
this.performances.addChangeListener { _, _ ->
this.updateRows()
}
this.reportSetups.addChangeListener { _, _ ->
this.updateRows()
}
this.performances.addChangeListener { _, _ ->
this.updateRows()
}
}
@ -293,7 +290,7 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc
*/
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()
return
}

@ -185,7 +185,7 @@ class SettingsFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRep
Preferences.setCurrencyCode(currencyCode, requireContext())
val realm = Realm.getDefaultInstance()
realm.executeTransactionAsync { execRealm->
executeRealmAsyncTransaction { execRealm->
execRealm.where(Currency::class.java).findAll().forEach { currency ->
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.FiltersActivity
import net.pokeranalytics.android.ui.modules.settings.TransactionFilterActivity
import net.pokeranalytics.android.util.Global
import timber.log.Timber
import java.util.*
@ -75,12 +74,10 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener {
this.currentFilterable = FilterableType.SESSION
applyFilter()
if (Global.LAUNCH_ASYNC_LISTENERS) {
addRealmChangeListener(this, UserConfig::class.java)
addRealmChangeListener(this, ComputableResult::class.java)
addRealmChangeListener(this, Transaction::class.java)
addRealmChangeListener(this, SessionSet::class.java)
}
addRealmChangeListener(this, UserConfig::class.java)
addRealmChangeListener(this, ComputableResult::class.java)
addRealmChangeListener(this, Transaction::class.java)
addRealmChangeListener(this, SessionSet::class.java)
}
private fun initUI() {

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

@ -1,14 +1,20 @@
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.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import io.realm.Realm
import io.realm.RealmModel
import io.realm.RealmResults
import net.pokeranalytics.android.AppState
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.util.Global
import net.pokeranalytics.android.ui.fragment.ImportBroadcast
interface RealmAsyncListener {
fun asyncListenedEntityChange(realm: Realm, clazz: Class<out RealmModel>)
@ -19,14 +25,21 @@ open class RealmFragment : BaseFragment() {
/**
* A realm instance
*/
private lateinit var realm: Realm
// private lateinit var realm: Realm
/***
* A listener to async updates
*/
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
@ -34,7 +47,8 @@ open class RealmFragment : BaseFragment() {
private var observedRealmResults: MutableList<RealmResults<*>> = mutableListOf()
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)
}
@ -42,7 +56,11 @@ open class RealmFragment : BaseFragment() {
* Get the realm instance
*/
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>) {
@ -52,23 +70,38 @@ open class RealmFragment : BaseFragment() {
}
this.changeListener = listener
val results = this.realm.where(clazz).findAllAsync()
val results = getRealm().where(clazz).findAllAsync()
results.addChangeListener { res, _ ->
// Timber.d("Realm changes: ${realmResults?.size}, $this")
this.changeListener?.asyncListenedEntityChange(res.realm, clazz)
if (!AppState.isImporting) {
this.changeListener?.asyncListenedEntityChange(res.realm, clazz)
} else {
this.changedClasses.add(clazz)
}
}
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() {
super.onDestroyView()
LocalBroadcastManager.getInstance(requireContext()).unregisterReceiver(endImportReceiver)
this.observedRealmResults.forEach {
it.removeAllChangeListeners()
}
this.realm.close()
this.realmResults?.removeAllChangeListeners()
}
/**

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

@ -141,7 +141,7 @@ class ProgressReportFragment : AbstractReportFragment() {
when (aggregationType) {
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()
return
}

@ -14,7 +14,7 @@ object AppReviewManager {
this.reviewRequested = true
}
fun showReviewManager(activity: Activity) {
fun showReviewManagerIfNecessary(activity: Activity) {
if (this.reviewRequested && this.shouldAskForReview(activity.baseContext)) {
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.BankrollTotalRow
import net.pokeranalytics.android.ui.view.rows.CustomizableRowRepresentable
import net.pokeranalytics.android.util.Global
import net.pokeranalytics.android.util.extensions.sorted
import timber.log.Timber
import java.util.*
import kotlin.collections.ArrayList
interface BankrollRowRepresentable : RowRepresentable {
var bankrollId: String?
@ -119,10 +116,8 @@ class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSour
private fun initData() {
this.bankrolls = getRealm().sorted()
if (Global.LAUNCH_ASYNC_LISTENERS) {
this.bankrolls.addChangeListener { _, _ ->
this.createRowRepresentables()
}
this.bankrolls.addChangeListener { _, _ ->
this.createRowRepresentables()
}
this.createRowRepresentables()

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

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

@ -69,7 +69,8 @@ open class EditableDataFragment : DataManagerFragment(), RowRepresentableDelegat
(this.model.item as RowUpdatable).updateValue(value, row)
if (this.model.primaryKey != null) {
getRealm().executeTransactionAsync { asyncRealm ->
executeRealmAsyncTransaction { asyncRealm ->
try {
asyncRealm.insertOrUpdate(this.model.item)
} catch (e: Exception) {
@ -77,6 +78,7 @@ open class EditableDataFragment : DataManagerFragment(), RowRepresentableDelegat
throw e
}
}
}
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.BadgeUtils
import com.google.android.material.tabs.TabLayout
import io.realm.Realm
import io.realm.RealmModel
import io.realm.RealmResults
import io.realm.Sort
import io.realm.*
import io.realm.kotlin.where
import net.pokeranalytics.android.R
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.extensions.count
import net.pokeranalytics.android.util.extensions.findById
import timber.log.Timber
import java.util.*
class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseListener, RealmAsyncListener {
@ -78,6 +76,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
private lateinit var realmTransactions: RealmResults<Transaction>
private lateinit var realmHandHistories: RealmResults<HandHistory>
// private lateinit var realmSessions: RealmResults<Session>
private var newSessionCreated: 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>) {
Timber.d("asyncListenedEntityChange for $clazz")
when (clazz.kotlin) {
Session::class -> {
Timber.d("WOWOWOOWOOWOWOWOWOWOWOWOWO")
this.sessionAdapter.refreshData()
this.sessionAdapter.notifyDataSetChanged()
}
@ -148,12 +149,30 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
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()
initData()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
getRealm().refresh()
if (requestCode == RequestCode.FEED_MENU.value && resultCode == RESULT_OK && data != null) {
when (data.getIntExtra(NewDataMenuActivity.IntentKey.CHOICE.keyName, -1)) {
0 -> createNewSession(false)
@ -489,7 +508,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis
private fun deleteSelectedTransaction() {
selectedTransaction?.id?.let { id ->
getRealm().executeTransactionAsync { asyncRealm ->
executeRealmAsyncTransaction { asyncRealm ->
asyncRealm.findById<Transaction>(id)?.deleteFromRealm()
}
}

@ -95,7 +95,7 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate {
val categoryRow = FilterCategoryRow.values()[category]
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)
} ?: throw PAIllegalStateException("Missing bundle")

@ -3,6 +3,7 @@ package net.pokeranalytics.android.ui.modules.filter
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import io.realm.Realm
import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
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 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 {
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()
val selectedRows = ArrayList<FilterItemRow>()
init {
this.rows.addAll(categoryRow.filterElements)
this.rows.addAll(categoryRow.filterElements(realm))
this.defineSelectedItems()
}

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

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

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

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

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

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

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

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

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

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

@ -4,12 +4,12 @@ buildscript {
ext.kotlin_version = '1.7.21'
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.2'
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
classpath 'com.google.gms:google-services:4.3.4'
@ -24,7 +24,7 @@ buildscript {
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}

Loading…
Cancel
Save