summaryrefslogtreecommitdiff
path: root/app/src/main/java/net/taler/wallet
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2019-09-01 18:33:03 +0200
committerFlorian Dold <florian.dold@gmail.com>2019-09-01 18:33:03 +0200
commit6f963cdfa0e918dbe35c99dafdb648dfa0586d7b (patch)
tree83ba25c8fa6d7f5eca46f38ba80e5040090436e4 /app/src/main/java/net/taler/wallet
parentb9fd051a1bf453e923ddbbf86cf8602d154278e1 (diff)
downloadwallet-android-6f963cdfa0e918dbe35c99dafdb648dfa0586d7b.tar.gz
wallet-android-6f963cdfa0e918dbe35c99dafdb648dfa0586d7b.tar.bz2
wallet-android-6f963cdfa0e918dbe35c99dafdb648dfa0586d7b.zip
withdraw via QR code, various bug fixes
Diffstat (limited to 'app/src/main/java/net/taler/wallet')
-rw-r--r--app/src/main/java/net/taler/wallet/MainActivity.kt41
-rw-r--r--app/src/main/java/net/taler/wallet/PromptPayment.kt2
-rw-r--r--app/src/main/java/net/taler/wallet/PromptWithdraw.kt101
-rw-r--r--app/src/main/java/net/taler/wallet/ShowBalance.kt38
-rw-r--r--app/src/main/java/net/taler/wallet/WalletViewModel.kt162
-rw-r--r--app/src/main/java/net/taler/wallet/WithdrawSuccessful.kt26
6 files changed, 305 insertions, 65 deletions
diff --git a/app/src/main/java/net/taler/wallet/MainActivity.kt b/app/src/main/java/net/taler/wallet/MainActivity.kt
index 44cd8a6..3d07821 100644
--- a/app/src/main/java/net/taler/wallet/MainActivity.kt
+++ b/app/src/main/java/net/taler/wallet/MainActivity.kt
@@ -18,6 +18,7 @@ import androidx.lifecycle.ViewModelProviders
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupWithNavController
+import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.navigation.NavigationView
import com.google.android.material.snackbar.Snackbar
import com.google.zxing.integration.android.IntentIntegrator
@@ -41,6 +42,14 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
navView.menu.getItem(0).isChecked = true
+ val fab: FloatingActionButton = findViewById(R.id.fab)
+ fab.setOnClickListener {
+ val integrator = IntentIntegrator(this)
+ integrator.setPrompt("Place merchant's QR Code inside the viewfinder rectangle to initiate payment.")
+ integrator.initiateScan(listOf("QR_CODE"))
+ }
+ fab.hide()
+
navView.setNavigationItemSelectedListener(this)
@@ -166,20 +175,26 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
}
val url = scanResult.contents!!
- if (!url.startsWith("talerpay:")) {
- val bar: Snackbar = Snackbar.make(
- findViewById(R.id.nav_host_fragment),
- "Scanned QR code doesn't contain Taler payment.",
- Snackbar.LENGTH_SHORT
- )
- bar.show()
- return
+ when {
+ url.startsWith("taler://pay") -> {
+ Log.v(TAG, "navigating!")
+ findNavController(R.id.nav_host_fragment).navigate(R.id.action_showBalance_to_promptPayment)
+ model.preparePay(url)
+ }
+ url.startsWith("taler://withdraw") -> {
+ Log.v(TAG, "navigating!")
+ findNavController(R.id.nav_host_fragment).navigate(R.id.action_showBalance_to_promptWithdraw)
+ model.getWithdrawalInfo(url)
+ }
+ else -> {
+ val bar: Snackbar = Snackbar.make(
+ findViewById(R.id.nav_host_fragment),
+ "Scanned QR code doesn't contain Taler payment.",
+ Snackbar.LENGTH_SHORT
+ )
+ bar.show()
+ }
}
-
- Log.v(TAG, "navigating!")
-
- findNavController(R.id.nav_host_fragment).navigate(R.id.action_showBalance_to_promptPayment)
- model.preparePay(url)
}
diff --git a/app/src/main/java/net/taler/wallet/PromptPayment.kt b/app/src/main/java/net/taler/wallet/PromptPayment.kt
index 07d3dd2..1d828e3 100644
--- a/app/src/main/java/net/taler/wallet/PromptPayment.kt
+++ b/app/src/main/java/net/taler/wallet/PromptPayment.kt
@@ -32,7 +32,7 @@ class PromptPayment : Fragment() {
var fragmentView: View? = null
- fun triggerLoading() {
+ private fun triggerLoading() {
val loading = model.payStatus.value == null || (model.payStatus.value is PayStatus.Loading)
val myActivity = activity!!
val progressBar = myActivity.findViewById<MaterialProgressBar>(R.id.progress_bar)
diff --git a/app/src/main/java/net/taler/wallet/PromptWithdraw.kt b/app/src/main/java/net/taler/wallet/PromptWithdraw.kt
new file mode 100644
index 0000000..785da42
--- /dev/null
+++ b/app/src/main/java/net/taler/wallet/PromptWithdraw.kt
@@ -0,0 +1,101 @@
+package net.taler.wallet
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.TextView
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProviders
+import androidx.navigation.findNavController
+import com.google.android.material.snackbar.Snackbar
+import me.zhanghai.android.materialprogressbar.MaterialProgressBar
+
+
+class PromptWithdraw : Fragment() {
+
+ private lateinit var model: WalletViewModel
+
+ private fun triggerLoading() {
+ val loading =
+ model.withdrawStatus.value is WithdrawStatus.Loading || model.withdrawStatus.value is WithdrawStatus.Withdrawing
+ val myActivity = activity!!
+ val progressBar = myActivity.findViewById<MaterialProgressBar>(R.id.progress_bar)
+ if (loading) {
+ progressBar.visibility = View.VISIBLE
+ } else {
+ progressBar.visibility = View.INVISIBLE
+ }
+ }
+
+ private fun showWithdrawStatus(view: View, status: WithdrawStatus) {
+ val confirmButton = view.findViewById<Button>(R.id.button_confirm_withdraw)
+ val promptWithdraw = view.findViewById<View>(R.id.prompt_withdraw)
+ when (status) {
+ is WithdrawStatus.ReceivedDetails -> {
+ promptWithdraw.visibility = View.VISIBLE
+ confirmButton.isEnabled = true
+ val promptWithdraw = view.findViewById<View>(R.id.prompt_withdraw)
+ promptWithdraw.visibility = View.VISIBLE
+ val amountView = view.findViewById<TextView>(R.id.withdraw_amount)
+ val exchangeView = view.findViewById<TextView>(R.id.withdraw_exchange)
+ exchangeView.text = status.suggestedExchange
+ @SuppressLint("SetTextI18n")
+ amountView.text = "${status.amount.amount} ${status.amount.currency}"
+ }
+ is WithdrawStatus.Success -> {
+ this.model.withdrawStatus.value = WithdrawStatus.None()
+ activity!!.findNavController(R.id.nav_host_fragment)
+ .navigate(R.id.action_promptWithdraw_to_withdrawSuccessful)
+ }
+ is WithdrawStatus.Loading -> {
+ promptWithdraw.visibility = View.INVISIBLE
+ // Wait
+ }
+ is WithdrawStatus.Withdrawing -> {
+ confirmButton.isEnabled = false
+
+ }
+ is WithdrawStatus.None -> {
+
+ }
+ else -> {
+ val bar = Snackbar.make(view, "Bug: Unexpected result", Snackbar.LENGTH_SHORT)
+ bar.show()
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ model = activity?.run {
+ ViewModelProviders.of(this)[WalletViewModel::class.java]
+ } ?: throw Exception("Invalid Activity")
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ val view = inflater.inflate(R.layout.fragment_prompt_withdraw, container, false)
+
+ this.model.withdrawStatus.observe(this, Observer {
+ triggerLoading()
+ showWithdrawStatus(view, it)
+ })
+
+ view.findViewById<Button>(R.id.button_confirm_withdraw).setOnClickListener {
+ val status = this.model.withdrawStatus.value
+ if (status !is WithdrawStatus.ReceivedDetails) {
+ return@setOnClickListener
+ }
+ model.acceptWithdrawal(status.talerWithdrawUri, status.suggestedExchange)
+ }
+
+ return view
+ }
+}
diff --git a/app/src/main/java/net/taler/wallet/ShowBalance.kt b/app/src/main/java/net/taler/wallet/ShowBalance.kt
index ba1bf14..a45d4fa 100644
--- a/app/src/main/java/net/taler/wallet/ShowBalance.kt
+++ b/app/src/main/java/net/taler/wallet/ShowBalance.kt
@@ -1,7 +1,6 @@
package net.taler.wallet
-import android.app.Activity
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
@@ -15,7 +14,6 @@ import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
-import com.google.android.material.snackbar.Snackbar
import com.google.zxing.integration.android.IntentIntegrator
import me.zhanghai.android.materialprogressbar.MaterialProgressBar
@@ -35,10 +33,22 @@ class MyAdapter(private var myDataset: WalletBalances) : RecyclerView.Adapter<My
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
+ val amount = myDataset.byCurrency[position].available
+ val amountIncoming = myDataset.byCurrency[position].pendingIncoming
val currencyView = holder.rowView.findViewById<TextView>(R.id.balance_currency)
- currencyView.text = myDataset.byCurrency[position].currency
+ currencyView.text = amount.currency
val amountView = holder.rowView.findViewById<TextView>(R.id.balance_amount)
- amountView.text = myDataset.byCurrency[position].amount
+ amountView.text = amount.amount
+
+ val amountIncomingRow = holder.rowView.findViewById<View>(R.id.balance_row_pending)
+
+ val amountIncomingView = holder.rowView.findViewById<TextView>(R.id.balance_pending)
+ if (amountIncoming.isZero()) {
+ amountIncomingRow.visibility = View.GONE
+ } else {
+ amountIncomingRow.visibility = View.VISIBLE
+ amountIncomingView.text = "${amountIncoming.amount} ${amountIncoming.currency}"
+ }
}
fun update(updatedBalances: WalletBalances) {
@@ -63,7 +73,7 @@ class ShowBalance : Fragment() {
fun triggerLoading() {
val loading: Boolean =
- (model.isBalanceLoading.value == true) || (model.balances.value == null) || !model.balances.value!!.initialized
+ (model.testWithdrawalInProgress.value == true) || (model.balances.value == null) || !model.balances.value!!.initialized
val myActivity = activity!!
val progressBar = myActivity.findViewById<MaterialProgressBar>(R.id.progress_bar)
@@ -87,11 +97,6 @@ class ShowBalance : Fragment() {
ViewModelProviders.of(this)[WalletViewModel::class.java]
} ?: throw Exception("Invalid Activity")
-
- model.isBalanceLoading.observe(this, Observer { loading ->
- Log.v("taler-wallet", "observing balance loading ${loading} in show balance")
- triggerLoading()
- })
}
@@ -129,13 +134,6 @@ class ShowBalance : Fragment() {
model.withdrawTestkudos()
}
- val payNfcButton = view.findViewById<Button>(R.id.button_pay_nfc)
- payNfcButton.setOnClickListener {
- val bar: Snackbar = Snackbar.make(view, "Sorry, NFC is not implemented yet!", Snackbar.LENGTH_SHORT)
- bar.show()
- }
-
-
this.balancesView = view.findViewById(R.id.list_balances)
this.balancesPlaceholderView = view.findViewById(R.id.list_balances_placeholder)
@@ -159,6 +157,12 @@ class ShowBalance : Fragment() {
updateBalances(it)
})
+ model.testWithdrawalInProgress.observe(this, Observer { loading ->
+ Log.v("taler-wallet", "observing balance loading ${loading} in show balance")
+ withdrawTestkudosButton.isEnabled = !loading
+ triggerLoading()
+ })
+
return view
}
}
diff --git a/app/src/main/java/net/taler/wallet/WalletViewModel.kt b/app/src/main/java/net/taler/wallet/WalletViewModel.kt
index f644c8d..356eb8a 100644
--- a/app/src/main/java/net/taler/wallet/WalletViewModel.kt
+++ b/app/src/main/java/net/taler/wallet/WalletViewModel.kt
@@ -9,13 +9,16 @@ import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import org.json.JSONObject
+import java.io.File
import java.io.InputStream
import java.lang.Exception
-import java.nio.file.Paths
val TAG = "taler-wallet"
-class AssetModuleLoader(private val assetManager: AssetManager, private val rootPath: String = "node_modules") :
+class AssetModuleLoader(
+ private val assetManager: AssetManager,
+ private val rootPath: String = "node_modules"
+) :
AkonoJni.LoadModuleHandler {
private fun makeResult(localPath: String, stream: InputStream): ModuleResult {
@@ -26,7 +29,8 @@ class AssetModuleLoader(private val assetManager: AssetManager, private val root
}
private fun tryPath(rawAssetPath: String): ModuleResult? {
- val assetPath = Paths.get(rawAssetPath).normalize().toString()
+ //val assetPath = Paths.get(rawAssetPath).normalize().toString()
+ val assetPath = File(rawAssetPath).normalize().path
try {
val moduleStream = assetManager.open(assetPath)
return makeResult(assetPath, moduleStream)
@@ -54,13 +58,15 @@ class AssetModuleLoader(private val assetManager: AssetManager, private val root
}
Log.i(TAG, "main field is $mainFile")
try {
- val modPath = Paths.get("$assetPath/$mainFile").normalize().toString()
+ //val modPath = Paths.get("$assetPath/$mainFile").normalize().toString()
+ val modPath = File("$assetPath/$mainFile").normalize().path
return makeResult(modPath, assetManager.open(modPath))
} catch (e: Exception) {
// ignore
}
try {
- val modPath = Paths.get("$assetPath/$mainFile.js").normalize().toString()
+ //val modPath = Paths.get("$assetPath/$mainFile.js").normalize().toString()
+ val modPath = File("$assetPath/$mainFile.js").normalize().path
return makeResult(modPath, assetManager.open(modPath))
} catch (e: Exception) {
}
@@ -105,7 +111,8 @@ class AssetDataHandler(private val assetManager: AssetManager) : AkonoJni.GetDat
override fun handleGetData(what: String): ByteArray? {
if (what == "taler-emscripten-lib.wasm") {
Log.i(TAG, "loading emscripten binary from taler-wallet")
- val stream = assetManager.open("node_modules/taler-wallet/emscripten/taler-emscripten-lib.wasm")
+ val stream =
+ assetManager.open("node_modules/taler-wallet/emscripten/taler-emscripten-lib.wasm")
val bytes: ByteArray = stream.readBytes()
Log.i(TAG, "size of emscripten binary: ${bytes.size}")
return bytes
@@ -117,16 +124,24 @@ class AssetDataHandler(private val assetManager: AssetManager) : AkonoJni.GetDat
}
data class Amount(val currency: String, val amount: String) {
+ fun isZero(): Boolean {
+ return amount.toDouble() == 0.0
+ }
+
companion object {
- val FRACTIONAL_BASE = 1e8;
+ const val FRACTIONAL_BASE = 1e8;
fun fromJson(jsonAmount: JSONObject): Amount {
val amountCurrency = jsonAmount.getString("currency")
val amountValue = jsonAmount.getString("value")
val amountFraction = jsonAmount.getString("fraction")
val amountIntValue = Integer.parseInt(amountValue)
val amountIntFraction = Integer.parseInt(amountFraction)
- return Amount(amountCurrency, (amountIntValue + amountIntFraction / FRACTIONAL_BASE).toString())
+ return Amount(
+ amountCurrency,
+ (amountIntValue + amountIntFraction / FRACTIONAL_BASE).toString()
+ )
}
+
fun fromString(strAmount: String): Amount {
val components = strAmount.split(":")
return Amount(components[0], components[1])
@@ -134,40 +149,60 @@ data class Amount(val currency: String, val amount: String) {
}
}
+data class BalanceEntry(val available: Amount, val pendingIncoming: Amount)
-data class WalletBalances(val initialized: Boolean, val byCurrency: List<Amount>)
+
+data class WalletBalances(val initialized: Boolean, val byCurrency: List<BalanceEntry>)
data class ContractTerms(val summary: String, val amount: Amount)
open class PayStatus {
class None : PayStatus()
class Loading : PayStatus()
- data class Prepared(val contractTerms: ContractTerms, val proposalId: Int, val totalFees: Amount) : PayStatus()
+ data class Prepared(
+ val contractTerms: ContractTerms,
+ val proposalId: Int,
+ val totalFees: Amount
+ ) : PayStatus()
+
data class InsufficientBalance(val contractTerms: ContractTerms) : PayStatus()
data class AlreadyPaid(val contractTerms: ContractTerms) : PayStatus()
data class Error(val error: String) : PayStatus()
class Success : PayStatus()
}
+open class WithdrawStatus {
+ class None : WithdrawStatus()
+ data class Loading(val talerWithdrawUri: String) : WithdrawStatus()
+ class Success : WithdrawStatus()
+ data class ReceivedDetails(
+ val talerWithdrawUri: String,
+ val amount: Amount,
+ val suggestedExchange: String
+ ) : WithdrawStatus()
+
+ data class Withdrawing(val talerWithdrawUri: String) : WithdrawStatus()
+}
+
class WalletViewModel(val app: Application) : AndroidViewModel(app) {
private lateinit var myAkono: AkonoJni
private var initialized = false
- private var withdrawInProgress: Int = 0
-
- val balances: MutableLiveData<WalletBalances> = MutableLiveData()
-
- val isBalanceLoading: MutableLiveData<Boolean> = MutableLiveData()
+ val testWithdrawalInProgress: MutableLiveData<Boolean> = MutableLiveData<Boolean>().apply {
+ value = false
+ }
- //val isProposalLoading: MutableLiveData<Boolean> = MutableLiveData()
+ val balances: MutableLiveData<WalletBalances> = MutableLiveData<WalletBalances>().apply {
+ value = WalletBalances(false, listOf())
+ }
- val payStatus: MutableLiveData<PayStatus> = MutableLiveData()
+ val payStatus: MutableLiveData<PayStatus> = MutableLiveData<PayStatus>().apply {
+ value = PayStatus.None()
+ }
- init {
- isBalanceLoading.value = false
- balances.value = WalletBalances(false, listOf())
- payStatus.value = PayStatus.None()
+ val withdrawStatus: MutableLiveData<WithdrawStatus> = MutableLiveData<WithdrawStatus>().apply {
+ value = WithdrawStatus.None()
}
fun init() {
@@ -201,23 +236,50 @@ class WalletViewModel(val app: Application) : AndroidViewModel(app) {
Log.v(TAG, "got response for operation $operation")
when (operation) {
"withdrawTestkudos" -> {
- withdrawInProgress--
- if (withdrawInProgress == 0) {
- isBalanceLoading.postValue(false)
- }
+ testWithdrawalInProgress.postValue(false)
}
"getBalances" -> {
- val balanceList = mutableListOf<Amount>();
+ val balanceList = mutableListOf<BalanceEntry>();
val result = message.getJSONObject("result")
val byCurrency = result.getJSONObject("byCurrency")
val currencyList = byCurrency.keys().asSequence().toList().sorted()
for (currency in currencyList) {
- val jsonAmount = byCurrency.getJSONObject(currency).getJSONObject("available")
+ val jsonAmount = byCurrency.getJSONObject(currency)
+ .getJSONObject("available")
val amount = Amount.fromJson(jsonAmount)
- balanceList.add(amount)
+ val jsonAmountIncoming = byCurrency.getJSONObject(currency)
+ .getJSONObject("pendingIncoming")
+ val amountIncoming = Amount.fromJson(jsonAmountIncoming)
+ balanceList.add(BalanceEntry(amount, amountIncoming))
}
balances.postValue(WalletBalances(true, balanceList))
}
+ "getWithdrawalInfo" -> {
+ Log.v(TAG, "got getWithdrawalInfo result")
+ val status = withdrawStatus.value
+ if (status !is WithdrawStatus.Loading) {
+ Log.v(TAG, "ignoring withdrawal info result, not loading.")
+ return
+ }
+ val result = message.getJSONObject("result")
+ val suggestedExchange = result.getString("suggestedExchange")
+ val amount = Amount.fromJson(result.getJSONObject("amount"))
+ withdrawStatus.postValue(
+ WithdrawStatus.ReceivedDetails(
+ status.talerWithdrawUri,
+ amount,
+ suggestedExchange
+ )
+ )
+ }
+ "acceptWithdrawal" -> {
+ Log.v(TAG, "got acceptWithdrawal result")
+ val status = withdrawStatus.value
+ if (status !is WithdrawStatus.Withdrawing) {
+ Log.v(TAG, "ignoring acceptWithdrawal result, invalid state")
+ }
+ withdrawStatus.postValue(WithdrawStatus.Success())
+ }
"preparePay" -> {
Log.v(TAG, "got preparePay result")
val result = message.getJSONObject("result")
@@ -238,9 +300,15 @@ class WalletViewModel(val app: Application) : AndroidViewModel(app) {
totalFees = Amount.fromJson(result.getJSONObject("totalFees"))
}
val res = when (status) {
- "payment-possible" -> PayStatus.Prepared(contractTerms!!, proposalId!!, totalFees!!)
+ "payment-possible" -> PayStatus.Prepared(
+ contractTerms!!,
+ proposalId!!,
+ totalFees!!
+ )
"paid" -> PayStatus.AlreadyPaid(contractTerms!!)
- "insufficient-balance" -> PayStatus.InsufficientBalance(contractTerms!!)
+ "insufficient-balance" -> PayStatus.InsufficientBalance(
+ contractTerms!!
+ )
"error" -> PayStatus.Error("got some error")
else -> PayStatus.Error("unkown status")
}
@@ -257,6 +325,7 @@ class WalletViewModel(val app: Application) : AndroidViewModel(app) {
})
myAkono.evalNodeCode("console.log('hello world from taler wallet-android')")
+ myAkono.evalNodeCode("require('source-map-support').install();")
myAkono.evalNodeCode("tw = require('taler-wallet');")
myAkono.evalNodeCode("tw.installAndroidWalletListener();")
@@ -296,8 +365,7 @@ class WalletViewModel(val app: Application) : AndroidViewModel(app) {
return
}
- withdrawInProgress++
- this.isBalanceLoading.value = true
+ testWithdrawalInProgress.value = true
val msg = JSONObject()
msg.put("operation", "withdrawTestkudos")
@@ -337,7 +405,7 @@ class WalletViewModel(val app: Application) : AndroidViewModel(app) {
sendInitMessage()
- isBalanceLoading.value = false
+ testWithdrawalInProgress.value = false
balances.value = WalletBalances(false, listOf())
getBalances()
@@ -365,6 +433,32 @@ class WalletViewModel(val app: Application) : AndroidViewModel(app) {
msg.put("args", respJson)
myAkono.sendMessage(msg.toString())
+ }
+
+ fun getWithdrawalInfo(talerWithdrawUri: String) {
+ val msg = JSONObject()
+ msg.put("operation", "getWithdrawalInfo")
+
+ val args = JSONObject()
+ msg.put("args", args)
+ args.put("talerWithdrawUri", talerWithdrawUri)
+
+ withdrawStatus.value = WithdrawStatus.Loading(talerWithdrawUri)
+
+ myAkono.sendMessage(msg.toString())
+ }
+
+ fun acceptWithdrawal(talerWithdrawUri: String, selectedExchange: String) {
+ val msg = JSONObject()
+ msg.put("operation", "acceptWithdrawal")
+ val args = JSONObject()
+ msg.put("args", args)
+ args.put("talerWithdrawUri", talerWithdrawUri)
+ args.put("selectedExchange", selectedExchange)
+
+ withdrawStatus.value = WithdrawStatus.Withdrawing(talerWithdrawUri)
+
+ myAkono.sendMessage(msg.toString())
}
-} \ No newline at end of file
+}
diff --git a/app/src/main/java/net/taler/wallet/WithdrawSuccessful.kt b/app/src/main/java/net/taler/wallet/WithdrawSuccessful.kt
new file mode 100644
index 0000000..c16dced
--- /dev/null
+++ b/app/src/main/java/net/taler/wallet/WithdrawSuccessful.kt
@@ -0,0 +1,26 @@
+package net.taler.wallet
+
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import androidx.navigation.findNavController
+
+/**
+ * A simple [Fragment] subclass.
+ */
+class WithdrawSuccessful : Fragment() {
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ val view = inflater.inflate(R.layout.fragment_withdraw_successful, container, false)
+ view.findViewById<Button>(R.id.button_success_back).setOnClickListener {
+ activity!!.findNavController(R.id.nav_host_fragment).navigateUp()
+ }
+ return view
+ }
+}