taler-android

Android apps for GNU Taler (wallet, PoS, cashier)
Log | Files | Refs | README | LICENSE

MainViewModel.kt (4327B)


      1 /*
      2  * This file is part of GNU Taler
      3  * (C) 2020 Taler Systems S.A.
      4  *
      5  * GNU Taler is free software; you can redistribute it and/or modify it under the
      6  * terms of the GNU General Public License as published by the Free Software
      7  * Foundation; either version 3, or (at your option) any later version.
      8  *
      9  * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
     10  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11  * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License along with
     14  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15  */
     16 
     17 package net.taler.cashier
     18 
     19 import android.app.Application
     20 import android.util.Log
     21 import androidx.lifecycle.AndroidViewModel
     22 import androidx.lifecycle.LiveData
     23 import androidx.lifecycle.MutableLiveData
     24 import androidx.lifecycle.viewModelScope
     25 import io.ktor.client.HttpClient
     26 import io.ktor.client.engine.okhttp.OkHttp
     27 import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
     28 import io.ktor.serialization.kotlinx.json.json
     29 import kotlinx.coroutines.Dispatchers
     30 import kotlinx.coroutines.launch
     31 import kotlinx.serialization.json.Json
     32 import net.taler.cashier.HttpHelper.makeJsonGetRequest
     33 import net.taler.cashier.config.ConfigManager
     34 import net.taler.cashier.withdraw.WithdrawManager
     35 import net.taler.common.Amount
     36 import net.taler.common.AmountParserException
     37 import net.taler.lib.android.isOnline
     38 
     39 private val TAG = MainViewModel::class.java.simpleName
     40 
     41 class MainViewModel(private val app: Application) : AndroidViewModel(app) {
     42 
     43     private val httpClient = HttpClient(OkHttp) {
     44         engine {
     45             config {
     46                 retryOnConnectionFailure(true)
     47             }
     48         }
     49         expectSuccess = true
     50         install(ContentNegotiation) {
     51             json(Json {
     52                 encodeDefaults = false
     53                 ignoreUnknownKeys = true
     54             })
     55         }
     56     }
     57     val configManager = ConfigManager(app, viewModelScope, httpClient)
     58 
     59     private val mBalance = MutableLiveData<BalanceResult>()
     60     val balance: LiveData<BalanceResult> = mBalance
     61 
     62     internal val withdrawManager = WithdrawManager(app, this)
     63 
     64     fun getBalance() = viewModelScope.launch(Dispatchers.IO) {
     65         check(configManager.hasConfig()) { "No config to get balance" }
     66         val config = configManager.config
     67         val url = "${config.bankUrl}/accounts/${config.username}"
     68         Log.d(TAG, "Checking balance at $url")
     69         val result = when (val response = makeJsonGetRequest(url, config)) {
     70             is HttpJsonResult.Success -> {
     71                 try {
     72                     val balanceObj = response.json.getJSONObject("balance")
     73                     val balanceAmount = balanceObj.getString("amount")
     74                     val debitThreshold = response.json.getString("debit_threshold")
     75                     val minCashout = if (response.json.has("min_cashout")) {
     76                         response.json.getString("min_cashout")
     77                     } else null
     78                     val positive = when (val creditDebitIndicator =
     79                         balanceObj.getString("credit_debit_indicator")) {
     80                         "credit" -> true
     81                         "debit" -> false
     82                         else -> throw AmountParserException("Unexpected credit_debit_indicator: $creditDebitIndicator")
     83                     }
     84                     BalanceResult.Success(
     85                         amount = SignedAmount(positive, Amount.fromJSONString(balanceAmount)),
     86                         debitThreshold = Amount.fromJSONString(debitThreshold),
     87                         minCashout = minCashout?.let { Amount.fromJSONString(it) }
     88 
     89                     )
     90                 } catch (e: Exception) {
     91                     Log.e(TAG, "Error parsing balance", e)
     92                     BalanceResult.Error("Invalid amount:\n${response.json.toString(2)}")
     93                 }
     94             }
     95             is HttpJsonResult.Error -> {
     96                 if (app.isOnline()) BalanceResult.Error(response.msg)
     97                 else BalanceResult.Offline
     98             }
     99         }
    100         mBalance.postValue(result)
    101     }
    102 
    103     fun lock() = viewModelScope.launch(Dispatchers.IO) {
    104         configManager.lock()
    105     }
    106 
    107 }