Currency API update

currency
Laurent 3 years ago
parent db5716971a
commit 1f595bc399
  1. 7
      app/build.gradle
  2. 43
      app/src/main/java/net/pokeranalytics/android/api/FreeConverterApi.kt
  3. 1
      app/src/main/java/net/pokeranalytics/android/model/filter/Query.kt
  4. 1
      app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt
  5. 1
      app/src/main/java/net/pokeranalytics/android/model/realm/FilterCondition.kt
  6. 2
      app/src/main/java/net/pokeranalytics/android/ui/activity/ImportActivity.kt
  7. 13
      app/src/main/java/net/pokeranalytics/android/ui/extensions/UIExtensions.kt
  8. 11
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/BaseFragment.kt
  9. 1
      app/src/main/java/net/pokeranalytics/android/ui/modules/calendar/CalendarDetailsFragment.kt
  10. 2
      app/src/main/java/net/pokeranalytics/android/ui/modules/calendar/CalendarFragment.kt
  11. 26
      app/src/main/java/net/pokeranalytics/android/ui/modules/data/BankrollDataFragment.kt
  12. 2
      app/src/main/java/net/pokeranalytics/android/ui/modules/data/PlayerDataFragment.kt
  13. 1
      app/src/main/java/net/pokeranalytics/android/ui/view/rows/FilterSectionRow.kt
  14. 5
      build.gradle

@ -6,7 +6,9 @@ apply plugin: 'realm-android'
// Crashlytics // Crashlytics
apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics' apply plugin: 'com.google.firebase.crashlytics'
////////////// // Serialization
apply plugin: "kotlinx-serialization"
repositories { repositories {
maven { url 'https://jitpack.io' } // required for MPAndroidChart maven { url 'https://jitpack.io' } // required for MPAndroidChart
@ -99,7 +101,8 @@ dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.6' 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-android:1.3.6"
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"
// Android // Android
implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.appcompat:appcompat:1.1.0'

@ -1,42 +1,53 @@
package net.pokeranalytics.android.api package net.pokeranalytics.android.api
import android.content.Context import android.content.Context
import com.android.volley.Request import com.android.volley.VolleyError
import com.android.volley.toolbox.StringRequest import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley import com.android.volley.toolbox.Volley
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import timber.log.Timber import timber.log.Timber
@Serializable
data class RateResponse(var info: RateInfo)
@Serializable
data class RateInfo(var rate: Double)
class FreeConverterApi { class FreeConverterApi {
companion object { companion object {
fun currencyRate(pair: String, context: Context, callback: (Double) -> (Unit)) { fun currencyRate(fromCurrency: String, toCurrency: String, context: Context, callback: (Double?, VolleyError?) -> (Unit)) {
val queue = Volley.newRequestQueue(context) val queue = Volley.newRequestQueue(context)
val url = "https://free.currconv.com/api/v7/convert?q=${pair}&compact=ultra&apiKey=9b56e742a75392c8aeb7" // val url = "https://free.currconv.com/api/v7/convert?q=${pair}&compact=ultra&apiKey=9b56e742a75392c8aeb7"
val url = "https://api.apilayer.com/exchangerates_data/convert?to=$toCurrency&from=$fromCurrency&amount=1"
// https://free.currconv.com/api/v7/convert?q=GBP_USD&compact=ultra&apiKey=5ba8d38995282fe8b1c8 // https://free.currconv.com/api/v7/convert?q=GBP_USD&compact=ultra&apiKey=5ba8d38995282fe8b1c8
// { "USD_PHP": 44.1105, "PHP_USD": 0.0227 } // { "USD_PHP": 44.1105, "PHP_USD": 0.0227 }
val stringRequest = StringRequest( Timber.d("Api call = $url")
Request.Method.GET, url,
{ response ->
val json = Json(JsonConfiguration.Stable)
val f = json.parseJson(response)
f.jsonObject[pair]?.primitive?.double?.let { rate ->
callback(rate)
} ?: run {
Timber.d("no rate: $response")
}
val stringRequest = object : StringRequest(
Method.GET, url,
{ response ->
val o = Json.decodeFromString<RateResponse>(response)
callback(o.info.rate, null)
}, },
{ {
callback(null, it)
Timber.d("Api call failed: ${it.message}") Timber.d("Api call failed: ${it.message}")
}) }) {
override fun getHeaders(): MutableMap<String, String> {
val headers = HashMap<String, String>()
headers["apikey"] = "XnfeyID3PMKd3k4zTPW0XmZAbcZlZgqH"
return headers
}
}
queue.add(stringRequest) queue.add(stringRequest)
} }

@ -119,6 +119,7 @@ class Query {
is QueryCondition.QueryDataCondition<*> -> { is QueryCondition.QueryDataCondition<*> -> {
c.objectId?.let { return it } c.objectId?.let { return it }
} }
else -> {}
} }
} }
return null return null

@ -848,6 +848,7 @@ sealed class QueryCondition : RowRepresentable {
} }
return realmQuery return realmQuery
} }
else -> {}
} }
if (this is CustomFieldRelated) { if (this is CustomFieldRelated) {

@ -29,6 +29,7 @@ open class FilterCondition() : RealmObject() {
is QueryCondition.ListOfDouble -> this.setValues(filterElementRows.flatMap { (it as QueryCondition.ListOfDouble).listOfValues }) is QueryCondition.ListOfDouble -> this.setValues(filterElementRows.flatMap { (it as QueryCondition.ListOfDouble).listOfValues })
is QueryCondition.ListOfInt -> this.setValues(filterElementRows.flatMap { (it as QueryCondition.ListOfInt).listOfValues }) is QueryCondition.ListOfInt -> this.setValues(filterElementRows.flatMap { (it as QueryCondition.ListOfInt).listOfValues })
is QueryCondition.ListOfString -> this.setValues(filterElementRows.flatMap { (it as QueryCondition.ListOfString).listOfValues }) is QueryCondition.ListOfString -> this.setValues(filterElementRows.flatMap { (it as QueryCondition.ListOfString).listOfValues })
else -> {}
} }
} }

@ -83,7 +83,7 @@ class ImportActivity : BaseActivity() {
when (requestCode) { when (requestCode) {
RequestCode.IMPORT.value -> { RequestCode.IMPORT.value -> {
if (resultCode == ResultCode.IMPORT_UNRECOGNIZED_FORMAT.value) { if (resultCode == ResultCode.IMPORT_UNRECOGNIZED_FORMAT.value) {
showAlertDialog(context = this, message = R.string.unknown_import_format_popup_message, positiveAction = { showAlertDialog(context = this, messageResId = R.string.unknown_import_format_popup_message, positiveAction = {
finish() finish()
}) })
} }

@ -3,7 +3,6 @@ package net.pokeranalytics.android.ui.extensions
import android.app.Activity import android.app.Activity
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
import android.content.Context import android.content.Context
import android.content.DialogInterface
import android.content.Intent import android.content.Intent
import android.content.res.Resources import android.content.res.Resources
import android.graphics.Bitmap import android.graphics.Bitmap
@ -147,9 +146,9 @@ fun Activity.showAlertDialog(title: Int? = null, message: Int? = null) {
showAlertDialog(this, title, message) showAlertDialog(this, title, message)
} }
fun Fragment.showAlertDialog(title: Int? = null, message: Int? = null) { fun Fragment.showAlertDialog(title: Int? = null, messageResId: Int? = null, message: String? = null) {
context?.let { context?.let {
showAlertDialog(it, title, message) showAlertDialog(it, title, messageResId, message)
} }
} }
@ -157,16 +156,20 @@ fun Fragment.showAlertDialog(title: Int? = null, message: Int? = null) {
* Create and show an alert dialog * Create and show an alert dialog
*/ */
fun showAlertDialog( fun showAlertDialog(
context: Context, title: Int? = null, message: Int? = null, cancelButtonTitle: Int? = null, showCancelButton: Boolean = false, context: Context, title: Int? = null, messageResId: Int? = null, message: String? = null, cancelButtonTitle: Int? = null, showCancelButton: Boolean = false,
positiveAction: (() -> Unit)? = null, negativeAction: (() -> Unit)? = null positiveAction: (() -> Unit)? = null, negativeAction: (() -> Unit)? = null
) { ) {
val builder = AlertDialog.Builder(context) val builder = AlertDialog.Builder(context)
title?.let { title?.let {
builder.setTitle(title) builder.setTitle(title)
} }
messageResId?.let {
builder.setMessage(messageResId)
}
message?.let { message?.let {
builder.setMessage(message) builder.setMessage(it)
} }
builder.setPositiveButton(net.pokeranalytics.android.R.string.ok) { _, _ -> builder.setPositiveButton(net.pokeranalytics.android.R.string.ok) { _, _ ->
positiveAction?.invoke() positiveAction?.invoke()
} }

@ -7,6 +7,7 @@ import android.os.Bundle
import android.view.View import android.view.View
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.google.android.material.snackbar.Snackbar
import net.pokeranalytics.android.PokerAnalyticsApplication import net.pokeranalytics.android.PokerAnalyticsApplication
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.activity.components.BaseActivity import net.pokeranalytics.android.ui.activity.components.BaseActivity
@ -15,6 +16,7 @@ import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheet
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.util.CrashLogging import net.pokeranalytics.android.util.CrashLogging
import timber.log.Timber
import java.io.File import java.io.File
import java.util.* import java.util.*
@ -183,4 +185,13 @@ abstract class BaseFragment : Fragment() {
return capability?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) ?: false return capability?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) ?: false
} }
fun showSnackBar(message: String) {
this.view?.let { view ->
val snackBar = Snackbar.make(view, message, Snackbar.LENGTH_INDEFINITE)
snackBar.show()
} ?: run {
Timber.d("No parent view for snackbar")
}
}
} }

@ -177,6 +177,7 @@ class CalendarDetailsFragment : BaseFragment(), StaticRowRepresentableDataSource
when (model.sessionTypeCondition) { when (model.sessionTypeCondition) {
QueryCondition.IsCash -> query.add(QueryCondition.IsCash) QueryCondition.IsCash -> query.add(QueryCondition.IsCash)
QueryCondition.IsTournament -> query.add(QueryCondition.IsTournament) QueryCondition.IsTournament -> query.add(QueryCondition.IsTournament)
else -> {}
} }
val requiredStats: List<Stat> = listOf(Stat.LOCATIONS_PLAYED, Stat.LONGEST_STREAKS, Stat.DAYS_PLAYED, Stat.STANDARD_DEVIATION_HOURLY) val requiredStats: List<Stat> = listOf(Stat.LOCATIONS_PLAYED, Stat.LONGEST_STREAKS, Stat.DAYS_PLAYED, Stat.STANDARD_DEVIATION_HOURLY)

@ -431,6 +431,7 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable
Calendar.MONTH, Calendar.MONTH,
condition.listOfValues.first() condition.listOfValues.first()
) )
else -> {}
} }
} }
@ -478,6 +479,7 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable
Calendar.YEAR, Calendar.YEAR,
condition.listOfValues.first() condition.listOfValues.first()
) )
else -> {}
} }
} }
yearlyReports[calendar.time] = computedResults yearlyReports[calendar.time] = computedResults

@ -15,6 +15,7 @@ import net.pokeranalytics.android.ui.activity.CurrenciesActivity
import net.pokeranalytics.android.ui.activity.components.RequestCode import net.pokeranalytics.android.ui.activity.components.RequestCode
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.extensions.toast
import net.pokeranalytics.android.ui.fragment.CurrenciesFragment import net.pokeranalytics.android.ui.fragment.CurrenciesFragment
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
@ -137,7 +138,7 @@ class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataS
override fun charSequenceForRow(row: RowRepresentable, context: Context, tag: Int): CharSequence { override fun charSequenceForRow(row: RowRepresentable, context: Context, tag: Int): CharSequence {
return when (row) { return when (row) {
SimpleRow.NAME -> if (bankroll.name.isNotEmpty()) bankroll.name else NULL_TEXT SimpleRow.NAME -> bankroll.name.ifEmpty { NULL_TEXT }
BankrollPropertiesRow.CURRENCY -> { BankrollPropertiesRow.CURRENCY -> {
bankroll.currency?.code?.let { code -> bankroll.currency?.code?.let { code ->
Currency.getInstance(code).currencyCode Currency.getInstance(code).currencyCode
@ -263,12 +264,24 @@ class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataS
} }
this.lastRefreshRateCall = System.currentTimeMillis() this.lastRefreshRateCall = System.currentTimeMillis()
val currenciesConverterValue = "${bankroll.currency?.code}_${defaultCurrency.currencyCode}" // val currenciesConverterValue = "${bankroll.currency?.code}_${defaultCurrency.currencyCode}"
FreeConverterApi.currencyRate(currenciesConverterValue, requireContext()) { rate -> bankroll.currency?.code?.let { from ->
onRowValueChanged(rate, BankrollPropertiesRow.RATE) val to = defaultCurrency.currencyCode
isRefreshingRate = false FreeConverterApi.currencyRate(from, to, requireContext()) { rate, error ->
rowRepresentableAdapter.refreshRow(BankrollPropertiesRow.REFRESH_RATE)
rate?.let {
onRowValueChanged(rate, BankrollPropertiesRow.RATE)
}
error?.localizedMessage?.let { message ->
toast(message)
}
// onRowValueChanged(rate, BankrollPropertiesRow.RATE)
isRefreshingRate = false
rowRepresentableAdapter.refreshRow(BankrollPropertiesRow.REFRESH_RATE)
}
} }
this.isRefreshingRate = true this.isRefreshingRate = true
@ -280,7 +293,6 @@ class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataS
this.bankrollModel.selectedCaptureType.value?.let { this.bankrollModel.selectedCaptureType.value?.let {
Preferences.setResultCaptureType(this.bankroll, it, requireContext()) Preferences.setResultCaptureType(this.bankroll, it, requireContext())
} }
} }
} }

@ -172,7 +172,7 @@ class PlayerDataFragment : EditableDataFragment(), StaticRowRepresentableDataSou
if (row.isValidForDelete(getRealm())) { if (row.isValidForDelete(getRealm())) {
GlobalScope.launch(Dispatchers.Main) { GlobalScope.launch(Dispatchers.Main) {
delay(300) delay(300)
showAlertDialog(requireContext(), message = R.string.are_you_sure_you_want_to_delete, showCancelButton = true, positiveAction = { showAlertDialog(requireContext(), messageResId = R.string.are_you_sure_you_want_to_delete, showCancelButton = true, positiveAction = {
player.deleteComment(row) player.deleteComment(row)
rowRepresentableAdapter.notifyDataSetChanged() rowRepresentableAdapter.notifyDataSetChanged()
}) })

@ -63,6 +63,7 @@ sealed class FilterSectionRow(override val resId: Int?) : RowRepresentable {
is CustomField -> { is CustomField -> {
return customField.name return customField.name
} }
else -> {}
} }
return name return name
} }

@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.5.21' ext.kotlin_version = '1.7.21'
repositories { repositories {
google() google()
jcenter() jcenter()
@ -15,6 +15,9 @@ buildscript {
classpath 'com.google.gms:google-services:4.3.4' classpath 'com.google.gms:google-services:4.3.4'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1'
// serialization
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
} }
} }

Loading…
Cancel
Save