aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTorsten Grote <t@grobox.de>2022-09-23 15:05:38 -0300
committerTorsten Grote <t@grobox.de>2022-09-23 15:05:38 -0300
commitbaca5eceb08055d35ef96d6d6586fbba55511d40 (patch)
tree26eaa30bde4d6d38775546bd5da811240d682e4e
parent54789b6adc3a7716c31b3d634b2afe55d95d9724 (diff)
downloadtaler-android-baca5eceb08055d35ef96d6d6586fbba55511d40.tar.gz
taler-android-baca5eceb08055d35ef96d6d6586fbba55511d40.tar.bz2
taler-android-baca5eceb08055d35ef96d6d6586fbba55511d40.zip
[wallet] Implement beginning of deposits
-rw-r--r--wallet/src/main/AndroidManifest.xml1
-rw-r--r--wallet/src/main/java/net/taler/wallet/MainActivity.kt7
-rw-r--r--wallet/src/main/java/net/taler/wallet/UriInputFragment.kt3
-rw-r--r--wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt22
-rw-r--r--wallet/src/main/java/net/taler/wallet/transactions/TransactionDepositFragment.kt105
-rw-r--r--wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt2
-rw-r--r--wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt40
-rw-r--r--wallet/src/main/res/navigation/nav_graph.xml10
-rw-r--r--wallet/src/main/res/values/strings.xml1
9 files changed, 177 insertions, 14 deletions
diff --git a/wallet/src/main/AndroidManifest.xml b/wallet/src/main/AndroidManifest.xml
index 69670c3..68bc321 100644
--- a/wallet/src/main/AndroidManifest.xml
+++ b/wallet/src/main/AndroidManifest.xml
@@ -63,6 +63,7 @@
<data
android:scheme="TALER"
tools:ignore="AppLinkUrlError" />
+ <data android:scheme="payto" />
</intent-filter>
</activity>
diff --git a/wallet/src/main/java/net/taler/wallet/MainActivity.kt b/wallet/src/main/java/net/taler/wallet/MainActivity.kt
index 5597564..cb48c30 100644
--- a/wallet/src/main/java/net/taler/wallet/MainActivity.kt
+++ b/wallet/src/main/java/net/taler/wallet/MainActivity.kt
@@ -203,9 +203,6 @@ class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener,
}
}
} else {
- if (!scheme.startsWith("taler", ignoreCase = true)) {
- return actionFound
- }
actionFound.postValue(uri.toString())
}
@@ -225,8 +222,8 @@ class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener,
val action = normalizedURL.substring(
if (normalizedURL.startsWith("taler://", ignoreCase = true)) {
"taler://".length
- } else if (normalizedURL.startsWith("taler+http://",
- ignoreCase = true) && model.devMode.value == true
+ } else if (normalizedURL.startsWith("taler+http://", ignoreCase = true) &&
+ model.devMode.value == true
) {
"taler+http://".length
} else {
diff --git a/wallet/src/main/java/net/taler/wallet/UriInputFragment.kt b/wallet/src/main/java/net/taler/wallet/UriInputFragment.kt
index 8ad1fb7..00ec404 100644
--- a/wallet/src/main/java/net/taler/wallet/UriInputFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/UriInputFragment.kt
@@ -59,7 +59,8 @@ class UriInputFragment : Fragment() {
}
}
ui.okButton.setOnClickListener {
- if (ui.uriView.text?.startsWith("taler://", ignoreCase = true) == true) {
+ if (ui.uriView.text?.startsWith("taler://", ignoreCase = true) == true ||
+ ui.uriView.text?.startsWith("payto://", ignoreCase = true) == true) {
ui.uriLayout.error = null
val i = Intent(ACTION_VIEW, Uri.parse(ui.uriView.text.toString()))
startActivity(i)
diff --git a/wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt b/wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt
index ae091df..b8918c1 100644
--- a/wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt
@@ -22,11 +22,12 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
+import kotlinx.serialization.Serializable
import net.taler.common.Amount
import net.taler.common.ContractTerms
import net.taler.wallet.TAG
-import net.taler.wallet.backend.WalletBackendApi
import net.taler.wallet.backend.TalerErrorInfo
+import net.taler.wallet.backend.WalletBackendApi
import net.taler.wallet.payment.PayStatus.AlreadyPaid
import net.taler.wallet.payment.PayStatus.InsufficientBalance
import net.taler.wallet.payment.PreparePayResponse.AlreadyConfirmedResponse
@@ -119,9 +120,28 @@ class PaymentManager(
mPayStatus.value = PayStatus.None
}
+ @UiThread
+ fun makeDeposit(url: String, amount: Amount) = scope.launch {
+ // TODO
+ api.request("createDepositGroup", CreateDepositGroupResponse.serializer()) {
+ put("depositPaytoUri", url)
+ put("amount", amount.toJSONString())
+ }.onError {
+ Log.e(TAG, "Error createDepositGroup $it")
+ }.onSuccess {
+ Log.e(TAG, "createDepositGroup $it")
+ }
+ }
+
private fun handleError(operation: String, error: TalerErrorInfo) {
Log.e(TAG, "got $operation error result $error")
mPayStatus.value = PayStatus.Error(error.userFacingMsg)
}
}
+
+@Serializable
+data class CreateDepositGroupResponse(
+ val depositGroupId: String,
+ val transactionId: String,
+)
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionDepositFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDepositFragment.kt
new file mode 100644
index 0000000..f721090
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDepositFragment.kt
@@ -0,0 +1,105 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2022 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.wallet.transactions
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material.Button
+import androidx.compose.material.ButtonDefaults
+import androidx.compose.material.Icon
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Surface
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment.Companion.CenterHorizontally
+import androidx.compose.ui.Alignment.Companion.CenterVertically
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import com.google.android.material.composethemeadapter.MdcTheme
+import net.taler.common.toAbsoluteTime
+import net.taler.wallet.R
+
+class TransactionDepositFragment : TransactionDetailFragment() {
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?,
+ ): View = ComposeView(requireContext()).apply {
+ setContent {
+ MdcTheme {
+ Surface {
+ val t = transaction ?: error("No transaction")
+ TransactionDepositComposable(t as TransactionDeposit) {
+ onDeleteButtonClicked(t)
+ }
+ }
+ }
+ }
+ }
+}
+
+@Composable
+fun TransactionDepositComposable(t: TransactionDeposit, onDelete: () -> Unit) {
+ val scrollState = rememberScrollState()
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .verticalScroll(scrollState),
+ horizontalAlignment = CenterHorizontally,
+ ) {
+ val context = LocalContext.current
+ Text(
+ modifier = Modifier.padding(16.dp),
+ text = t.timestamp.ms.toAbsoluteTime(context).toString(),
+ style = MaterialTheme.typography.body1,
+ )
+ // TODO
+ Button(
+ modifier = Modifier.padding(16.dp),
+ colors = ButtonDefaults.buttonColors(backgroundColor = colorResource(R.color.red)),
+ onClick = onDelete,
+ ) {
+ Row(verticalAlignment = CenterVertically) {
+ Icon(
+ painter = painterResource(id = R.drawable.ic_delete),
+ contentDescription = null,
+ tint = Color.White,
+ )
+ Text(
+ modifier = Modifier.padding(start = 8.dp),
+ text = stringResource(R.string.transactions_delete),
+ color = Color.White,
+ )
+ }
+ }
+ }
+}
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
index d1020e2..bbae22b 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
@@ -89,7 +89,7 @@ class TransactionManager(
}
}
- fun deleteTransaction(transactionId: String) = scope.launch {
+ fun deleteTransaction(transactionId: String) = scope.launch {
api.request<Unit>("deleteTransaction") {
put("transactionId", transactionId)
}.onError {
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt b/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt
index 97ac5ea..dcb524e 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt
@@ -75,7 +75,7 @@ class TransactionWithdrawal(
val withdrawalDetails: WithdrawalDetails,
override val error: TalerErrorInfo? = null,
override val amountRaw: Amount,
- override val amountEffective: Amount
+ override val amountEffective: Amount,
) : Transaction() {
override val icon = R.drawable.transaction_withdrawal
@@ -102,7 +102,7 @@ sealed class WithdrawalDetails {
*
* Already contains the amount and message.
*/
- val exchangePaytoUris: List<String>
+ val exchangePaytoUris: List<String>,
) : WithdrawalDetails()
@Serializable
@@ -133,7 +133,7 @@ class TransactionPayment(
val status: PaymentStatus,
override val error: TalerErrorInfo? = null,
override val amountRaw: Amount,
- override val amountEffective: Amount
+ override val amountEffective: Amount,
) : Transaction() {
override val icon = R.drawable.ic_cash_usd_outline
override val detailPageNav = R.id.action_nav_transactions_detail_payment
@@ -192,7 +192,7 @@ class TransactionRefund(
val amountInvalid: Amount? = null,
override val error: TalerErrorInfo? = null,
override val amountRaw: Amount,
- override val amountEffective: Amount
+ override val amountEffective: Amount,
) : Transaction() {
override val icon = R.drawable.transaction_refund
override val detailPageNav = R.id.action_nav_transactions_detail_refund
@@ -216,7 +216,7 @@ class TransactionTip(
val merchantBaseUrl: String,
override val error: TalerErrorInfo? = null,
override val amountRaw: Amount,
- override val amountEffective: Amount
+ override val amountEffective: Amount,
) : Transaction() {
override val icon = R.drawable.transaction_tip_accepted // TODO different when declined
override val detailPageNav = 0
@@ -239,7 +239,7 @@ class TransactionRefresh(
val exchangeBaseUrl: String,
override val error: TalerErrorInfo? = null,
override val amountRaw: Amount,
- override val amountEffective: Amount
+ override val amountEffective: Amount,
) : Transaction() {
override val icon = R.drawable.transaction_refresh
override val detailPageNav = R.id.action_nav_transactions_detail_refresh
@@ -254,6 +254,30 @@ class TransactionRefresh(
}
@Serializable
+@SerialName("deposit")
+class TransactionDeposit(
+ override val transactionId: String,
+ override val timestamp: Timestamp,
+ override val pending: Boolean,
+ override val error: TalerErrorInfo? = null,
+ override val amountRaw: Amount,
+ override val amountEffective: Amount,
+ val targetPaytoUri: String,
+ val depositGroupId: String,
+) : Transaction() {
+ override val icon = R.drawable.ic_cash_usd_outline
+ override val detailPageNav = R.id.action_nav_transactions_detail_deposit
+
+ @Transient
+ override val amountType = AmountType.Negative
+ override fun getTitle(context: Context): String {
+ return context.getString(R.string.transaction_deposit)
+ }
+
+ override val generalTitleRes = R.string.transaction_deposit
+}
+
+@Serializable
data class PeerInfoShort(
val expiration: Timestamp? = null,
val summary: String? = null,
@@ -282,6 +306,7 @@ class TransactionPeerPullDebit(
override fun getTitle(context: Context): String {
return context.getString(R.string.transaction_peer_pull_debit)
}
+
override val generalTitleRes = R.string.transaction_peer_pull_debit
}
@@ -309,6 +334,7 @@ class TransactionPeerPullCredit(
override fun getTitle(context: Context): String {
return context.getString(R.string.transaction_peer_pull_credit)
}
+
override val generalTitleRes = R.string.transaction_peer_pull_credit
}
@@ -337,6 +363,7 @@ class TransactionPeerPushDebit(
override fun getTitle(context: Context): String {
return context.getString(R.string.transaction_peer_push_debit)
}
+
override val generalTitleRes = R.string.payment_title
}
@@ -363,5 +390,6 @@ class TransactionPeerPushCredit(
override fun getTitle(context: Context): String {
return context.getString(R.string.transaction_peer_push_credit)
}
+
override val generalTitleRes = R.string.transaction_peer_push_credit
}
diff --git a/wallet/src/main/res/navigation/nav_graph.xml b/wallet/src/main/res/navigation/nav_graph.xml
index f9060c5..96ca49f 100644
--- a/wallet/src/main/res/navigation/nav_graph.xml
+++ b/wallet/src/main/res/navigation/nav_graph.xml
@@ -199,6 +199,12 @@
tools:layout="@layout/fragment_transaction_withdrawal" />
<fragment
+ android:id="@+id/nav_transactions_detail_deposit"
+ android:name="net.taler.wallet.transactions.TransactionDepositFragment"
+ android:label="@string/transactions_detail_title"
+ tools:layout="@layout/fragment_transaction_withdrawal" />
+
+ <fragment
android:id="@+id/nav_transactions_detail_peer"
android:name="net.taler.wallet.transactions.TransactionPeerFragment"
android:label="@string/transactions_detail_title"
@@ -323,4 +329,8 @@
android:id="@+id/action_nav_transactions_detail_refresh"
app:destination="@id/nav_transactions_detail_refresh" />
+ <action
+ android:id="@+id/action_nav_transactions_detail_deposit"
+ app:destination="@id/nav_transactions_detail_deposit" />
+
</navigation>
diff --git a/wallet/src/main/res/values/strings.xml b/wallet/src/main/res/values/strings.xml
index 52700b8..6d5f554 100644
--- a/wallet/src/main/res/values/strings.xml
+++ b/wallet/src/main/res/values/strings.xml
@@ -96,6 +96,7 @@ GNU Taler is immune against many types of fraud, such as phishing of credit card
<string name="transaction_refund_from">Refund from %s</string>
<string name="transaction_pending">PENDING</string>
<string name="transaction_refresh">Coin expiry change fee</string>
+ <string name="transaction_deposit">Deposit</string>
<string name="transaction_peer_push_debit">Push payment</string>
<string name="transaction_peer_pull_credit">Invoice</string>
<string name="transaction_peer_pull_debit">Invoice paid</string>