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
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
//////////////
// Serialization
apply plugin: "kotlinx-serialization"
repositories {
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-android:1.3.6"
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
implementation 'androidx.appcompat:appcompat:1.1.0'

@ -1,42 +1,53 @@
package net.pokeranalytics.android.api
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.Volley
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import timber.log.Timber
@Serializable
data class RateResponse(var info: RateInfo)
@Serializable
data class RateInfo(var rate: Double)
class FreeConverterApi {
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 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
// { "USD_PHP": 44.1105, "PHP_USD": 0.0227 }
val stringRequest = StringRequest(
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")
}
Timber.d("Api call = $url")
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}")
})
}) {
override fun getHeaders(): MutableMap<String, String> {
val headers = HashMap<String, String>()
headers["apikey"] = "XnfeyID3PMKd3k4zTPW0XmZAbcZlZgqH"
return headers
}
}
queue.add(stringRequest)
}

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

@ -848,6 +848,7 @@ sealed class QueryCondition : RowRepresentable {
}
return realmQuery
}
else -> {}
}
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.ListOfInt -> this.setValues(filterElementRows.flatMap { (it as QueryCondition.ListOfInt).listOfValues })
is QueryCondition.ListOfString -> this.setValues(filterElementRows.flatMap { (it as QueryCondition.ListOfString).listOfValues })
else -> {}
}
}

@ -83,7 +83,7 @@ class ImportActivity : BaseActivity() {
when (requestCode) {
RequestCode.IMPORT.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()
})
}

@ -3,7 +3,6 @@ package net.pokeranalytics.android.ui.extensions
import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.res.Resources
import android.graphics.Bitmap
@ -147,9 +146,9 @@ fun Activity.showAlertDialog(title: Int? = null, message: Int? = null) {
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 {
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
*/
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
) {
val builder = AlertDialog.Builder(context)
title?.let {
builder.setTitle(title)
}
messageResId?.let {
builder.setMessage(messageResId)
}
message?.let {
builder.setMessage(message)
builder.setMessage(it)
}
builder.setPositiveButton(net.pokeranalytics.android.R.string.ok) { _, _ ->
positiveAction?.invoke()
}

@ -7,6 +7,7 @@ import android.os.Bundle
import android.view.View
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.Fragment
import com.google.android.material.snackbar.Snackbar
import net.pokeranalytics.android.PokerAnalyticsApplication
import net.pokeranalytics.android.R
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.RowRepresentableEditDescriptor
import net.pokeranalytics.android.util.CrashLogging
import timber.log.Timber
import java.io.File
import java.util.*
@ -183,4 +185,13 @@ abstract class BaseFragment : Fragment() {
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) {
QueryCondition.IsCash -> query.add(QueryCondition.IsCash)
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)

@ -431,6 +431,7 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable
Calendar.MONTH,
condition.listOfValues.first()
)
else -> {}
}
}
@ -478,6 +479,7 @@ class CalendarFragment : RealmFragment(), CoroutineScope, StaticRowRepresentable
Calendar.YEAR,
condition.listOfValues.first()
)
else -> {}
}
}
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.adapter.RowRepresentableDataSource
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.view.RowRepresentable
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 {
return when (row) {
SimpleRow.NAME -> if (bankroll.name.isNotEmpty()) bankroll.name else NULL_TEXT
SimpleRow.NAME -> bankroll.name.ifEmpty { NULL_TEXT }
BankrollPropertiesRow.CURRENCY -> {
bankroll.currency?.code?.let { code ->
Currency.getInstance(code).currencyCode
@ -263,12 +264,24 @@ class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataS
}
this.lastRefreshRateCall = System.currentTimeMillis()
val currenciesConverterValue = "${bankroll.currency?.code}_${defaultCurrency.currencyCode}"
// val currenciesConverterValue = "${bankroll.currency?.code}_${defaultCurrency.currencyCode}"
FreeConverterApi.currencyRate(currenciesConverterValue, requireContext()) { rate ->
onRowValueChanged(rate, BankrollPropertiesRow.RATE)
isRefreshingRate = false
rowRepresentableAdapter.refreshRow(BankrollPropertiesRow.REFRESH_RATE)
bankroll.currency?.code?.let { from ->
val to = defaultCurrency.currencyCode
FreeConverterApi.currencyRate(from, to, requireContext()) { rate, error ->
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
@ -280,7 +293,6 @@ class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataS
this.bankrollModel.selectedCaptureType.value?.let {
Preferences.setResultCaptureType(this.bankroll, it, requireContext())
}
}
}

@ -172,7 +172,7 @@ class PlayerDataFragment : EditableDataFragment(), StaticRowRepresentableDataSou
if (row.isValidForDelete(getRealm())) {
GlobalScope.launch(Dispatchers.Main) {
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)
rowRepresentableAdapter.notifyDataSetChanged()
})

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

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

Loading…
Cancel
Save