Ask for rate when changing main currency

currency
Laurent 3 years ago
parent 1f595bc399
commit c90f4cd52f
  1. 10
      app/src/main/java/net/pokeranalytics/android/api/CurrencyConverterApi.kt
  2. 317
      app/src/main/java/net/pokeranalytics/android/ui/extensions/UIExtensions.kt
  3. 7
      app/src/main/java/net/pokeranalytics/android/ui/fragment/CurrenciesFragment.kt
  4. 61
      app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt
  5. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/components/LoaderDialogFragment.kt
  6. 8
      app/src/main/java/net/pokeranalytics/android/ui/fragment/report/AbstractReportFragment.kt
  7. 4
      app/src/main/java/net/pokeranalytics/android/ui/modules/data/BankrollDataFragment.kt
  8. 2
      app/src/main/res/values-de/strings.xml
  9. 2
      app/src/main/res/values-es/strings.xml
  10. 2
      app/src/main/res/values-fr/strings.xml
  11. 2
      app/src/main/res/values-hi/strings.xml
  12. 2
      app/src/main/res/values-it/strings.xml
  13. 2
      app/src/main/res/values-ja/strings.xml
  14. 2
      app/src/main/res/values-pt/strings.xml
  15. 2
      app/src/main/res/values-ru/strings.xml
  16. 2
      app/src/main/res/values-zh/strings.xml
  17. 2
      app/src/main/res/values/strings.xml

@ -14,10 +14,12 @@ data class RateResponse(var info: RateInfo)
@Serializable
data class RateInfo(var rate: Double)
class FreeConverterApi {
class CurrencyConverterApi {
companion object {
val json = Json { ignoreUnknownKeys = true }
fun currencyRate(fromCurrency: String, toCurrency: String, context: Context, callback: (Double?, VolleyError?) -> (Unit)) {
val queue = Volley.newRequestQueue(context)
@ -33,12 +35,14 @@ class FreeConverterApi {
val stringRequest = object : StringRequest(
Method.GET, url,
{ response ->
val o = Json.decodeFromString<RateResponse>(response)
val o = json.decodeFromString<RateResponse>(response)
Timber.d("rate = ${o.info.rate}")
callback(o.info.rate, null)
},
{
callback(null, it)
Timber.d("Api call failed: ${it.message}")
callback(null, it)
}) {
override fun getHeaders(): MutableMap<String, String> {

@ -9,13 +9,11 @@ import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.net.Uri
import android.text.SpannableStringBuilder
import android.util.TypedValue
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import android.widget.*
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.SearchView
import androidx.core.content.ContextCompat
@ -36,216 +34,245 @@ import java.io.File
// Sizes
val Int.dp: Int
get() = (this / Resources.getSystem().displayMetrics.density).toInt()
get() = (this / Resources.getSystem().displayMetrics.density).toInt()
val Int.px: Int
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
val Float.dp: Float
get() = (this / Resources.getSystem().displayMetrics.density)
get() = (this / Resources.getSystem().displayMetrics.density)
val Float.px: Float
get() = (this * Resources.getSystem().displayMetrics.density)
get() = (this * Resources.getSystem().displayMetrics.density)
// Toast
fun Activity.toast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
fun Fragment.toast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}
// Open Play Store for rating
fun Activity.openPlayStorePage() {
val uri = Uri.parse("market://details?id=$packageName")
val goToMarket = Intent(Intent.ACTION_VIEW, uri)
goToMarket.addFlags(
Intent.FLAG_ACTIVITY_NO_HISTORY or Intent.FLAG_ACTIVITY_NEW_DOCUMENT or
Intent.FLAG_ACTIVITY_MULTIPLE_TASK
)
try {
startActivity(goToMarket)
} catch (e: ActivityNotFoundException) {
startActivity(
Intent(
Intent.ACTION_VIEW, Uri.parse(
"http://play.google.com/store/apps/details?id=$packageName"
)
)
)
}
val uri = Uri.parse("market://details?id=$packageName")
val goToMarket = Intent(Intent.ACTION_VIEW, uri)
goToMarket.addFlags(
Intent.FLAG_ACTIVITY_NO_HISTORY or Intent.FLAG_ACTIVITY_NEW_DOCUMENT or
Intent.FLAG_ACTIVITY_MULTIPLE_TASK
)
try {
startActivity(goToMarket)
} catch (e: ActivityNotFoundException) {
startActivity(
Intent(
Intent.ACTION_VIEW, Uri.parse(
"http://play.google.com/store/apps/details?id=$packageName"
)
)
)
}
}
// Open email for "Contact us"
fun BaseActivity.openContactMail(subjectStringRes: Int, filePath: String? = null) {
val info =
"v${BuildConfig.VERSION_NAME}(${BuildConfig.VERSION_CODE}) - ${AppGuard.isProUser}, Android ${android.os.Build.VERSION.SDK_INT}, ${DeviceUtils.getDeviceName()}"
val emailIntent = Intent(Intent.ACTION_SEND)
filePath?.let {
val databaseFile = File(it)
val contentUri = FileProvider.getUriForFile(this, "net.pokeranalytics.android.fileprovider", databaseFile)
if (contentUri != null) {
emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
emailIntent.setDataAndType(contentUri, contentResolver.getType(contentUri))
emailIntent.putExtra(Intent.EXTRA_STREAM, contentUri)
}
}
emailIntent.type = "message/rfc822"
emailIntent.putExtra(Intent.EXTRA_SUBJECT, getString(subjectStringRes))
emailIntent.putExtra(Intent.EXTRA_TEXT, "\n\n$info")
emailIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf(URL.SUPPORT_EMAIL.value))
startActivity(Intent.createChooser(emailIntent, getString(R.string.contact)))
val info =
"v${BuildConfig.VERSION_NAME}(${BuildConfig.VERSION_CODE}) - ${AppGuard.isProUser}, Android ${android.os.Build.VERSION.SDK_INT}, ${DeviceUtils.getDeviceName()}"
val emailIntent = Intent(Intent.ACTION_SEND)
filePath?.let {
val databaseFile = File(it)
val contentUri = FileProvider.getUriForFile(
this,
"net.pokeranalytics.android.fileprovider",
databaseFile
)
if (contentUri != null) {
emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
emailIntent.setDataAndType(contentUri, contentResolver.getType(contentUri))
emailIntent.putExtra(Intent.EXTRA_STREAM, contentUri)
}
}
emailIntent.type = "message/rfc822"
emailIntent.putExtra(Intent.EXTRA_SUBJECT, getString(subjectStringRes))
emailIntent.putExtra(Intent.EXTRA_TEXT, "\n\n$info")
emailIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf(URL.SUPPORT_EMAIL.value))
startActivity(Intent.createChooser(emailIntent, getString(R.string.contact)))
}
// Open custom tab
fun Context.openUrl(url: String) {
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
ContextCompat.startActivity(this, browserIntent, null)
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
ContextCompat.startActivity(this, browserIntent, null)
}
// Open custom tab
fun Context.areYouSure(title: Int? = null, message: Int? = null, positiveTitle: Int? = null, proceed: () -> Unit) {
val builder: android.app.AlertDialog.Builder = android.app.AlertDialog.Builder(this)
val messageResource = message ?: R.string.are_you_sure_you_want_to_do_this
builder.setMessage(messageResource)
fun Context.areYouSure(
title: Int? = null,
message: Int? = null,
positiveTitle: Int? = null,
proceed: () -> Unit
) {
title?.let { builder.setTitle(it) }
val builder: android.app.AlertDialog.Builder = android.app.AlertDialog.Builder(this)
val positiveButtonTitle = positiveTitle ?: R.string.yes
builder.setPositiveButton(positiveButtonTitle) { _, _ ->
proceed()
}
builder.setNegativeButton(R.string.cancel) { _, _ ->
// nothing
}
val messageResource = message ?: R.string.are_you_sure_you_want_to_do_this
builder.setMessage(messageResource)
// builder.setItems(
// arrayOf<CharSequence>(
// getString(R.string.yes),
// getString(R.string.cancel)
// )
// ) { _, index ->
// // The 'which' argument contains the index position
// // of the selected item
// when (index) {
// 0 -> proceed()
// 1 -> {} // nothing
// }
// }
builder.create().show()
title?.let { builder.setTitle(it) }
val positiveButtonTitle = positiveTitle ?: R.string.yes
builder.setPositiveButton(positiveButtonTitle) { _, _ ->
proceed()
}
builder.setNegativeButton(R.string.cancel) { _, _ ->
// nothing
}
builder.create().show()
}
// Display Alert Dialog
fun Activity.showAlertDialog(title: Int? = null, message: Int? = null) {
showAlertDialog(this, title, message)
showAlertDialog(this, title, message)
}
fun Fragment.showAlertDialog(title: Int? = null, messageResId: Int? = null, message: String? = null) {
context?.let {
showAlertDialog(it, title, messageResId, message)
}
fun Fragment.showAlertDialog(
title: Int? = null,
messageResId: Int? = null,
message: String? = null
) {
context?.let {
showAlertDialog(it, title, messageResId, message)
}
}
fun showEditTextAlertDialog(
context: Context, inputType: Int, title: Int? = null, messageResId: Int? = null, message: String? = null,
editTextText: String? = null, positiveAction: ((String) -> Unit)? = null
) {
val builder = AlertDialog.Builder(context)
title?.let {
builder.setTitle(title)
}
messageResId?.let {
builder.setMessage(messageResId)
}
message?.let {
builder.setMessage(it)
}
val editText = EditText(context)
editTextText?.let {
editText.text = SpannableStringBuilder(it)
}
editText.setTextColor(ContextCompat.getColor(context, R.color.white))
editText.inputType = inputType
builder.setView(editText)
builder.setPositiveButton(net.pokeranalytics.android.R.string.ok) { _, _ ->
positiveAction?.invoke(editText.text.toString())
}
builder.show()
}
/**
* Create and show an alert dialog
*/
fun showAlertDialog(
context: Context, title: Int? = null, messageResId: Int? = null, message: String? = null, cancelButtonTitle: Int? = null, showCancelButton: Boolean = false,
positiveAction: (() -> Unit)? = null, negativeAction: (() -> Unit)? = null
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(it)
}
builder.setPositiveButton(net.pokeranalytics.android.R.string.ok) { _, _ ->
positiveAction?.invoke()
}
if (cancelButtonTitle != null) {
builder.setNegativeButton(cancelButtonTitle) { _, _ ->
negativeAction?.invoke()
}
} else if (showCancelButton) {
builder.setNegativeButton(R.string.cancel) { _, _ ->
negativeAction?.invoke()
}
}
builder.show()
val builder = AlertDialog.Builder(context)
title?.let {
builder.setTitle(title)
}
messageResId?.let {
builder.setMessage(messageResId)
}
message?.let {
builder.setMessage(it)
}
builder.setPositiveButton(net.pokeranalytics.android.R.string.ok) { _, _ ->
positiveAction?.invoke()
}
if (cancelButtonTitle != null) {
builder.setNegativeButton(cancelButtonTitle) { _, _ ->
negativeAction?.invoke()
}
} else if (showCancelButton) {
builder.setNegativeButton(R.string.cancel) { _, _ ->
negativeAction?.invoke()
}
}
builder.show()
}
fun TextView.setTextFormat(textFormat: TextFormat, context: Context) {
this.setTextColor(textFormat.getColor(context))
this.text = textFormat.text
this.setTextColor(textFormat.getColor(context))
this.text = textFormat.text
}
fun View.hideWithAnimation() {
isVisible = true
animate().cancel()
animate().alpha(0f).withEndAction { isVisible = false }.start()
isVisible = true
animate().cancel()
animate().alpha(0f).withEndAction { isVisible = false }.start()
}
fun View.showWithAnimation() {
isVisible = true
animate().cancel()
animate().alpha(1f).start()
isVisible = true
animate().cancel()
animate().alpha(1f).start()
}
fun View.addCircleRipple() = with(TypedValue()) {
context.theme.resolveAttribute(android.R.attr.selectableItemBackgroundBorderless, this, true)
setBackgroundResource(resourceId)
context.theme.resolveAttribute(android.R.attr.selectableItemBackgroundBorderless, this, true)
setBackgroundResource(resourceId)
}
fun SearchView.removeMargins() {
val searchEditFrame = findViewById<LinearLayout?>(R.id.search_edit_frame)
val layoutParams = searchEditFrame?.layoutParams as LinearLayout.LayoutParams?
layoutParams?.leftMargin = 0
layoutParams?.rightMargin = 0
searchEditFrame?.layoutParams = layoutParams
val searchEditFrame = findViewById<LinearLayout?>(R.id.search_edit_frame)
val layoutParams = searchEditFrame?.layoutParams as LinearLayout.LayoutParams?
layoutParams?.leftMargin = 0
layoutParams?.rightMargin = 0
searchEditFrame?.layoutParams = layoutParams
}
fun View.toByteArray() : ByteArray {
return this.convertToBitmap().toByteArray()
fun View.toByteArray(): ByteArray {
return this.convertToBitmap().toByteArray()
}
fun View.convertToBitmap(): Bitmap {
val b = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(b)
val background = this.background
this.background?.let {
background.draw(canvas)
} ?: run {
canvas.drawColor(Color.WHITE)
}
this.draw(canvas)
return b
val b = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(b)
val background = this.background
this.background?.let {
background.draw(canvas)
} ?: run {
canvas.drawColor(Color.WHITE)
}
this.draw(canvas)
return b
}
fun ImageView.toByteArray() : ByteArray {
return this.drawable.toBitmap().toByteArray()
fun ImageView.toByteArray(): ByteArray {
return this.drawable.toBitmap().toByteArray()
}
fun Bitmap.toByteArray() : ByteArray {
val baos = ByteArrayOutputStream()
this.compress(Bitmap.CompressFormat.PNG, 100, baos)
return baos.toByteArray()
fun Bitmap.toByteArray(): ByteArray {
val baos = ByteArrayOutputStream()
this.compress(Bitmap.CompressFormat.PNG, 100, baos)
return baos.toByteArray()
}
fun Context.hideKeyboard(v: View) {
val imm = v.context.getSystemService(InputMethodManager::class.java)
imm?.hideSoftInputFromWindow(v.windowToken, 0)
val imm = v.context.getSystemService(InputMethodManager::class.java)
imm?.hideSoftInputFromWindow(v.windowToken, 0)
}
//fun Context.showKeyboard(view: View) {

@ -65,8 +65,8 @@ class CurrenciesFragment : BaseFragment(), StaticRowRepresentableDataSource, Row
}
var currencyCode: String = currency.currencyCode
var currencySymbole: String = currency.getSymbol(Locale.getDefault())
var currencyCodeAndSymbol: String = "${this.currencyCode} (${this.currencySymbole})"
var currencySymbol: String = currency.getSymbol(Locale.getDefault())
var currencyCodeAndSymbol: String = "${this.currencyCode} (${this.currencySymbol})"
override val viewType: Int = RowViewType.TITLE_VALUE.ordinal
}
@ -110,6 +110,9 @@ class CurrenciesFragment : BaseFragment(), StaticRowRepresentableDataSource, Row
// RowRepresentableDelegate
override fun onRowSelected(position: Int, row: RowRepresentable, tag: Int) {
val intent = Intent()
intent.putExtra(INTENT_CURRENCY_CODE, (row as CurrencyRow).currency.currencyCode)
this.activity?.setResult(Activity.RESULT_OK, intent)

@ -6,6 +6,7 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.text.InputType
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -17,6 +18,7 @@ import com.google.android.play.core.review.ReviewManagerFactory
import io.realm.Realm
import net.pokeranalytics.android.BuildConfig
import net.pokeranalytics.android.R
import net.pokeranalytics.android.api.CurrencyConverterApi
import net.pokeranalytics.android.databinding.FragmentSettingsBinding
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.LiveData
@ -33,6 +35,7 @@ import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.extensions.openContactMail
import net.pokeranalytics.android.ui.extensions.openUrl
import net.pokeranalytics.android.ui.extensions.showEditTextAlertDialog
import net.pokeranalytics.android.ui.fragment.components.RealmFragment
import net.pokeranalytics.android.ui.modules.bankroll.BankrollActivity
import net.pokeranalytics.android.ui.modules.datalist.DataListActivity
@ -141,19 +144,7 @@ class SettingsFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRep
if (resultCode == Activity.RESULT_OK) {
data?.let {
val currencyCode = data.getStringExtra(CurrenciesFragment.INTENT_CURRENCY_CODE) ?: throw PAIllegalStateException("Missing currency code")
Preferences.setCurrencyCode(currencyCode, requireContext())
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
realm.where(Currency::class.java).isNull("code").or().equalTo("code", UserDefaults.currency.currencyCode).findAll().forEach { currency ->
currency.rate = Currency.DEFAULT_RATE
}
realm.where(Session::class.java).isNull("bankroll.currency.code").findAll().forEach { session ->
session.bankrollHasBeenUpdated()
}
}
realm.close()
settingsAdapterRow.refreshRow(SettingsRow.CURRENCY)
updateMainCurrency(currencyCode)
}
}
}
@ -163,6 +154,50 @@ class SettingsFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRep
}
}
private fun updateMainCurrency(currencyCode: String) {
Preferences.getDefaultCurrency(requireContext())?.currencyCode?.let { mainCurrencyCode ->
if (mainCurrencyCode == currencyCode) {
return
}
showLoader(R.string.please_wait)
CurrencyConverterApi.currencyRate(mainCurrencyCode, currencyCode, requireContext()) { apiRate, _ ->
hideLoader()
val message = requireContext().getString(R.string.currency_rate_confirmation, mainCurrencyCode, currencyCode)
// val message = "Please enter the $mainCurrencyCode to $currencyCode rate to apply to all your bankrolls"
showEditTextAlertDialog(requireContext(), InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL,
message = message, editTextText = apiRate?.toString()) { value ->
value.toDoubleOrNull()?.let { rate ->
updateMainCurrency(currencyCode, rate)
}
}
}
}
}
private fun updateMainCurrency(currencyCode: String, rate: Double) {
Preferences.setCurrencyCode(currencyCode, requireContext())
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
realm.where(Currency::class.java).findAll().forEach { currency ->
currency.rate = (currency.rate ?: 1.0) * rate
}
realm.where(Session::class.java).findAll().forEach { session ->
session.bankrollHasBeenUpdated()
}
}
realm.close()
settingsAdapterRow.refreshRow(SettingsRow.CURRENCY)
}
override fun adapterRows(): List<RowRepresentable> {
return rowRepresentation
}

@ -47,7 +47,7 @@ class LoaderDialogFragment: DialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
arguments?.let {bundle ->
arguments?.let { bundle ->
if (bundle.containsKey(ARGUMENT_MESSAGE_RES_ID)) {
binding.loadingMessage.text = getString(bundle.getInt(ARGUMENT_MESSAGE_RES_ID))
}

@ -68,9 +68,9 @@ abstract class AbstractReportFragment : DataManagerFragment() {
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
val view = inflater.inflate(net.pokeranalytics.android.R.layout.dialog_edit_text, null)
val view = inflater.inflate(R.layout.dialog_edit_text, null)
val nameEditText =
view.findViewById<EditText>(net.pokeranalytics.android.R.id.reportName)
view.findViewById<EditText>(R.id.reportName)
nameEditText.inputType = InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
this.model.primaryKey?.let { id ->
@ -81,7 +81,7 @@ abstract class AbstractReportFragment : DataManagerFragment() {
builder.setView(view)
// Add action buttons
.setPositiveButton(net.pokeranalytics.android.R.string.save) { dialog, _ ->
.setPositiveButton(R.string.save) { dialog, _ ->
try {
saveReport(nameEditText.text.toString())
dialog.dismiss()
@ -89,7 +89,7 @@ abstract class AbstractReportFragment : DataManagerFragment() {
Toast.makeText(requireContext(), e.localizedMessage, Toast.LENGTH_SHORT).show()
}
}
.setNegativeButton(net.pokeranalytics.android.R.string.cancel) { dialog, _ ->
.setNegativeButton(R.string.cancel) { dialog, _ ->
dialog.cancel()
}

@ -8,7 +8,7 @@ import android.view.View
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModelProvider
import net.pokeranalytics.android.R
import net.pokeranalytics.android.api.FreeConverterApi
import net.pokeranalytics.android.api.CurrencyConverterApi
import net.pokeranalytics.android.model.realm.Bankroll
import net.pokeranalytics.android.model.realm.ResultCaptureType
import net.pokeranalytics.android.ui.activity.CurrenciesActivity
@ -268,7 +268,7 @@ class BankrollDataFragment : EditableDataFragment(), StaticRowRepresentableDataS
bankroll.currency?.code?.let { from ->
val to = defaultCurrency.currencyCode
FreeConverterApi.currencyRate(from, to, requireContext()) { rate, error ->
CurrencyConverterApi.currencyRate(from, to, requireContext()) { rate, error ->
rate?.let {
onRowValueChanged(rate, BankrollPropertiesRow.RATE)

@ -779,5 +779,7 @@
<string name="more_sign"><![CDATA[>]]></string>
<string name="less_or_equal_sign"><![CDATA[≤]]></string>
<string name="less_sign"><![CDATA[<]]></string>
<string name="please_wait">Please wait…</string>
<string name="currency_rate_confirmation">Please enter the %1$s to %2$s rate to apply to all your bankrolls</string>
</resources>

@ -783,6 +783,8 @@ La aplicación funciona con una suscripción anual para uso ilimitado, pero obti
<string name="more_sign"><![CDATA[>]]></string>
<string name="less_or_equal_sign"><![CDATA[≤]]></string>
<string name="less_sign"><![CDATA[<]]></string>
<string name="please_wait">Please wait…</string>
<string name="currency_rate_confirmation">Please enter the %1$s to %2$s rate to apply to all your bankrolls</string>
</resources>

@ -788,5 +788,7 @@
<string name="less_or_equal_sign"><![CDATA[≤]]></string>
<string name="less_sign"><![CDATA[<]]></string>
<string name="transaction_filter">Filtre de transactions</string>
<string name="please_wait">Veuillez patienter…</string>
<string name="currency_rate_confirmation">Veuillez entrer le taux de %1$s vers %2$s pour l\'appliquer à toutes vos bankrolls</string>
</resources>

@ -778,5 +778,7 @@
<string name="more_sign"><![CDATA[>]]></string>
<string name="less_or_equal_sign"><![CDATA[≤]]></string>
<string name="less_sign"><![CDATA[<]]></string>
<string name="please_wait">Please wait…</string>
<string name="currency_rate_confirmation">Please enter the %1$s to %2$s rate to apply to all your bankrolls</string>
</resources>

@ -778,5 +778,7 @@
<string name="more_sign"><![CDATA[>]]></string>
<string name="less_or_equal_sign"><![CDATA[≤]]></string>
<string name="less_sign"><![CDATA[<]]></string>
<string name="please_wait">Please wait…</string>
<string name="currency_rate_confirmation">Please enter the %1$s to %2$s rate to apply to all your bankrolls</string>
</resources>

@ -782,5 +782,7 @@
<string name="more_sign"><![CDATA[>]]></string>
<string name="less_or_equal_sign"><![CDATA[≤]]></string>
<string name="less_sign"><![CDATA[<]]></string>
<string name="please_wait">Please wait…...</string>
<string name="currency_rate_confirmation">Please enter the %1$s to %2$s rate to apply to all your bankrolls</string>
</resources>

@ -777,5 +777,7 @@
<string name="more_sign"><![CDATA[>]]></string>
<string name="less_or_equal_sign"><![CDATA[≤]]></string>
<string name="less_sign"><![CDATA[<]]></string>
<string name="please_wait">Please wait…</string>
<string name="currency_rate_confirmation">Please enter the %1$s to %2$s rate to apply to all your bankrolls</string>
</resources>

@ -779,5 +779,7 @@
<string name="more_sign"><![CDATA[>]]></string>
<string name="less_or_equal_sign"><![CDATA[≤]]></string>
<string name="less_sign"><![CDATA[<]]></string>
<string name="please_wait">Please wait…</string>
<string name="currency_rate_confirmation">Please enter the %1$s to %2$s rate to apply to all your bankrolls</string>
</resources>

@ -772,5 +772,7 @@
<string name="more_sign"><![CDATA[>]]></string>
<string name="less_or_equal_sign"><![CDATA[≤]]></string>
<string name="less_sign"><![CDATA[<]]></string>
<string name="please_wait">Please wait…</string>
<string name="currency_rate_confirmation">Please enter the %1$s to %2$s rate to apply to all your bankrolls</string>
</resources>

@ -832,5 +832,7 @@
<string name="less_sign"><![CDATA[<]]></string>
<string name="empty_reports_screen">This screen will show where you perform the best when you\'ll have more data. You also can create custom reports using the top right button.</string>
<string name="transaction_filter">Transaction Filter</string>
<string name="please_wait">Please wait…</string>
<string name="currency_rate_confirmation">Please enter the %1$s to %2$s rate to apply to all your bankrolls</string>
</resources>

Loading…
Cancel
Save