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

dev
Aurelien Hubert 7 years ago
commit c77b739eb5
  1. 8
      app/build.gradle
  2. 13
      app/src/main/AndroidManifest.xml
  3. 14
      app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt
  4. 7
      app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt
  5. 4
      app/src/main/java/net/pokeranalytics/android/model/utils/SessionSetManager.kt
  6. 37
      app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt
  7. 61
      app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt
  8. 13
      app/src/main/java/net/pokeranalytics/android/ui/fragment/ImportFragment.kt
  9. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/DataManagerFragment.kt
  10. 68
      app/src/main/java/net/pokeranalytics/android/util/csv/CSVImporter.kt
  11. 2
      app/src/main/res/values-fr/strings.xml
  12. 1
      app/src/main/res/values/strings.xml

@ -72,7 +72,7 @@ dependencies {
// Android
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.core:core-ktx:1.1.0-alpha05'
implementation 'androidx.core:core-ktx:1.2.0-alpha01'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
@ -88,13 +88,15 @@ dependencies {
implementation 'com.google.android.libraries.places:places:1.1.0'
// Billing / Subscriptions
// WARNING FOR 2.0: https://developer.android.com/google/play/billing/billing_library_releases_notes
// Purchases MUST BE ACKNOWLEDGED
implementation 'com.android.billingclient:billing:1.2.2'
// Firebase
implementation 'com.google.firebase:firebase-core:16.0.8'
implementation 'com.google.firebase:firebase-core:16.0.9'
// Crashlytics
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.9'
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
// Logs
implementation 'com.jakewharton.timber:timber:4.7.1'

@ -22,6 +22,7 @@
<activity
android:name="net.pokeranalytics.android.ui.activity.HomeActivity"
android:launchMode="singleInstance"
android:label="@string/app_name"
android:screenOrientation="portrait">
<intent-filter>
@ -30,11 +31,6 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="net.pokeranalytics.android.ui.activity.ImportActivity"
android:launchMode="singleTop">
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW" />
@ -49,6 +45,13 @@
</activity>
<activity
android:name="net.pokeranalytics.android.ui.activity.ImportActivity"
android:screenOrientation="portrait"
android:launchMode="singleTop">
</activity>
<activity
android:name="net.pokeranalytics.android.ui.activity.SessionActivity"
android:launchMode="singleTop"

@ -11,7 +11,9 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import net.pokeranalytics.android.model.migrations.Patcher
import net.pokeranalytics.android.model.migrations.PokerAnalyticsMigration
import net.pokeranalytics.android.model.realm.ComputableResult
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.SessionSet
import net.pokeranalytics.android.model.utils.Seed
import net.pokeranalytics.android.util.FakeDataManager
import net.pokeranalytics.android.util.PokerAnalyticsLogs
@ -40,11 +42,13 @@ class PokerAnalyticsApplication : Application() {
.build()
Realm.setDefaultConfiguration(realmConfiguration)
// val realm = Realm.getDefaultInstance()
// realm.executeTransaction {
// realm.where(Session::class.java).findAll().deleteAllFromRealm()
// }
// realm.close()
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
realm.where(Session::class.java).findAll().deleteAllFromRealm()
realm.where(ComputableResult::class.java).findAll().deleteAllFromRealm()
realm.where(SessionSet::class.java).findAll().deleteAllFromRealm()
}
realm.close()
// Set up Crashlytics, disabled for debug builds
val crashlyticsKit = Crashlytics.Builder()

@ -101,12 +101,13 @@ open class Bankroll : RealmObject(), NameManageable, RowRepresentable {
fun getOrCreate(realm: Realm, name: String, live: Boolean = true, currencyCode: String? = null, currencyRate: Double? = null) : Bankroll {
val bankroll = realm.where<Bankroll>().equalTo("name", name).findFirst()
return if (bankroll != null) {
bankroll
val br = realm.where<Bankroll>().equalTo("name", name).findFirst()
return if (br != null) {
br
} else {
val bankroll = Bankroll()
bankroll.name = name
bankroll.live = live
val currency = Currency()
currency.code = currencyCode
currency.rate = currencyRate

@ -7,9 +7,7 @@ import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.SessionSet
import kotlin.math.max
class CorruptSessionSetException(message: String) : Exception(message) {
}
class CorruptSessionSetException(message: String) : Exception(message)
/**
* The manager is in charge of updating the abstract concept of timeline,

@ -3,6 +3,7 @@ package net.pokeranalytics.android.ui.activity
import android.app.KeyguardManager
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import com.google.android.material.bottomnavigation.BottomNavigationView
@ -13,7 +14,9 @@ import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.Currency
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.adapter.HomePagerAdapter
import net.pokeranalytics.android.ui.extensions.showAlertDialog
import net.pokeranalytics.android.util.billing.AppGuard
import timber.log.Timber
class HomeActivity : PokerAnalyticsActivity() {
@ -75,6 +78,30 @@ class HomeActivity : PokerAnalyticsActivity() {
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
intent?.let {
when (intent.action) {
"android.intent.action.VIEW" -> { // import
val data = it.data
if (data != null) {
this.requestImportConfirmation(data)
} else {
throw IllegalStateException("URI null on import")
}
}
else -> {
Timber.d("Intent ${intent.action} unmanaged")
}
}
}
}
private fun observeRealmObjects() {
val realm = getRealm()
@ -125,4 +152,14 @@ class HomeActivity : PokerAnalyticsActivity() {
viewPager.setCurrentItem(index, false)
}
// Import
fun requestImportConfirmation(uri: Uri) {
showAlertDialog(this, R.string.import_confirmation, showCancelButton = true, positiveAction = {
ImportActivity.newInstance(this, uri)
})
}
}

@ -1,12 +1,9 @@
package net.pokeranalytics.android.ui.activity
import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import android.os.PersistableBundle
import androidx.core.app.ActivityCompat
import io.realm.Realm
import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
@ -15,8 +12,10 @@ import timber.log.Timber
class ImportActivity : PokerAnalyticsActivity() {
private lateinit var fileURI: Uri
enum class IntentKey(val keyName: String) {
FILE_PATH("filepath")
URI("uri")
}
companion object {
@ -24,25 +23,24 @@ class ImportActivity : PokerAnalyticsActivity() {
/**
* Create a new instance for result
*/
fun newInstance(context: Context, filePath: String) {
context.startActivity(getIntent(context, filePath))
fun newInstance(context: Context, uri: Uri) {
context.startActivity(getIntent(context, uri))
}
private fun getIntent(context: Context, filePath: String) : Intent {
private fun getIntent(context: Context, uri: Uri) : Intent {
val intent = Intent(context, ImportActivity::class.java)
intent.putExtra(ImportActivity.IntentKey.FILE_PATH.keyName, filePath)
intent.putExtra(ImportActivity.IntentKey.URI.keyName, uri)
return intent
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
this.fileURI = intent.getParcelableExtra(ImportActivity.IntentKey.URI.keyName)
setContentView(R.layout.activity_import)
initUI()
}
override fun onStop() {
@ -59,32 +57,27 @@ class ImportActivity : PokerAnalyticsActivity() {
val fragmentTransaction = supportFragmentManager.beginTransaction()
val fragment = ImportFragment()
val filePath = intent.getStringExtra(ImportActivity.IntentKey.FILE_PATH.keyName)
fragment.setData(filePath)
val fis = contentResolver.openInputStream(fileURI)
Timber.d("Load fragment data with: $fis")
fis?.let {
fragment.setData(it)
}
fragmentTransaction.add(R.id.container, fragment)
fragmentTransaction.commit()
}
private fun requestPermission() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
ActivityCompat.requestPermissions(
this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), PERMISSION_REQUEST_ACCESS_FINE_LOCATION
)
}
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
val f = intent?.data
val uri = f.toString()
Timber.d("!!!Intent!!! uri = $uri")
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
// private fun requestPermission() {
// if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
// ActivityCompat.requestPermissions(
// this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), PERMISSION_REQUEST_ACCESS_FINE_LOCATION
// )
// }
// }
//
// override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
// super.onRequestPermissionsResult(requestCode, permissions, grantResults)
// }
}

@ -12,6 +12,7 @@ import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.fragment.components.RealmFragment
import net.pokeranalytics.android.util.csv.CSVImporter
import timber.log.Timber
import java.io.InputStream
import java.util.*
import kotlin.coroutines.CoroutineContext
@ -21,11 +22,17 @@ class ImportFragment : RealmFragment() {
get() = Dispatchers.Main
private lateinit var filePath: String
private lateinit var inputStream: InputStream
fun setData(path: String) {
this.filePath = path
}
fun setData(inputStream: InputStream) {
Timber.d("> setData with IS...")
this.inputStream = inputStream
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_import, container, false)
@ -33,6 +40,8 @@ class ImportFragment : RealmFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Timber.d("> onViewCreated...")
this.startImport()
}
@ -42,9 +51,9 @@ class ImportFragment : RealmFragment() {
val test = GlobalScope.async {
val s = Date()
Timber.d(">>> start...")
Timber.d(">>> Start Import...")
val csv = CSVImporter(filePath)
val csv = CSVImporter(inputStream)
csv.start()
val e = Date()

@ -95,7 +95,7 @@ open class DataManagerFragment : RealmFragment() {
this.getRealm().executeTransaction {
val managedItem = it.copyToRealmOrUpdate(this.item)
if (managedItem is Savable) {
val uniqueIdentifier = (managedItem as Savable).id
val uniqueIdentifier = managedItem.id
finishActivityWithResult(uniqueIdentifier)
}
}

@ -5,8 +5,24 @@ import org.apache.commons.csv.CSVFormat
import org.apache.commons.csv.CSVRecord
import timber.log.Timber
import java.io.FileReader
import java.io.InputStream
import java.io.InputStreamReader
import java.io.Reader
open class CSVImporter(var path: String) {
open class CSVImporter {
private val COMMIT_FREQUENCY = 100
var path: String? = null
var inputStream: InputStream? = null
constructor(istream: InputStream) {
inputStream = istream
}
constructor(filePath: String) {
path = filePath
}
private var usedDescriptors: MutableList<CSVDescriptor> = mutableListOf()
private var currentDescriptor: CSVDescriptor? = null
@ -15,40 +31,52 @@ open class CSVImporter(var path: String) {
val realm = Realm.getDefaultInstance()
val reader = FileReader(this.path)
var reader: Reader? = null
if (this.path != null) {
reader = FileReader(this.path)
}
if (this.inputStream != null) {
reader = InputStreamReader(this.inputStream)
}
val parser = CSVFormat.DEFAULT.withAllowMissingColumnNames().parse(reader)
Timber.d("Starting import...")
realm.executeTransaction {
realm.beginTransaction()
parser.forEachIndexed { index, record ->
parser.forEachIndexed { index, record ->
Timber.d("line $index")
Timber.d("line $index")
if (currentDescriptor == null) { // find descriptor
this.findDescriptor(record)
} else {
if (currentDescriptor == null) { // find descriptor
this.findDescriptor(record)
} else {
currentDescriptor?.let {
if (record.size() == 0) {
this.usedDescriptors.add(it)
this.currentDescriptor = null // reset descriptor when encountering an empty line (multiple descriptors can be found in a single file)
} else {
it.parse(realm, record)
}
} ?: run {
throw IllegalStateException("CSVDescriptor should never be null here")
}
if ((index + 1) % COMMIT_FREQUENCY == 0) {
Timber.d("****** committing at ${index} sessions...")
realm.commitTransaction()
realm.beginTransaction()
}
currentDescriptor?.let {
if (record.size() == 0) {
this.usedDescriptors.add(it)
this.currentDescriptor =
null // reset descriptor when encountering an empty line (multiple descriptors can be found in a single file)
} else {
it.parse(realm, record)
}
} ?: run {
throw IllegalStateException("CSVDescriptor should never be null here")
}
}
}
Timber.d("Ending import...")
realm.commitTransaction()
// this.save(realm)
Timber.d("Ending import...")
realm.close()
}

@ -379,7 +379,7 @@
<string name="operation_empty_field_error">Vérifiez que la transaction possède un type et un montant</string>
<string name="operation_type_empty_field_error">Il faut choisir un nom!</string>
<string name="operation_types">Types de transactions</string>
<string name="operations">Transaction</string>
<string name="operations">Transactions</string>
<string name="other">Autres</string>
<string name="password_explanation">Choisissez un code PIN pour\n protéger l\'accès à l\'application.\nUn code PIN ne peut pas être retrouvé.\nSoyez attentif lors de l\'activation\n de cette fonction.</string>
<string name="password_protection">Code PIN</string>

@ -31,6 +31,7 @@
<string name="launch_report">Launch Report</string>
<string name="progress">Progress</string>
<string name="save_report">Save Report</string>
<string name="import_confirmation">Do you want to proceed with the file import?</string>
<string name="update_entity" formatted="false">Update %s</string>
<string name="comparison_chart">Comparison chart</string>
<string name="filter_currently_selected">The filter cannot be deleted because it is currently selected.</string>

Loading…
Cancel
Save