taler-android

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

commit e3ae33d3f0f0b3450a580729345d07c0f6a994af
parent e0d848d525f42c5319ca65235ac9b33fa14a3f68
Author: Iván Ávalos <avalos@disroot.org>
Date:   Sat, 28 Feb 2026 23:28:16 +0100

[wallet] fix #11136 (empty balances screen)

Diffstat:
Mwallet/src/main/java/net/taler/wallet/balances/BalanceManager.kt | 5+++++
Mwallet/src/main/java/net/taler/wallet/balances/BalancesComposable.kt | 111++++++++++++++++++++++++++++++++-----------------------------------------------
Awallet/src/main/java/net/taler/wallet/balances/EmptyBalancesComposable.kt | 143+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mwallet/src/main/java/net/taler/wallet/exchanges/ExchangeManager.kt | 3++-
Mwallet/src/main/java/net/taler/wallet/main/MainComposable.kt | 4++++
Mwallet/src/main/java/net/taler/wallet/main/MainFragment.kt | 26++++++++++++++++++++++++++
Awallet/src/main/res/drawable-night/ic_taler_full.xml | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Awallet/src/main/res/drawable/ic_taler_full.xml | 39+++++++++++++++++++++++++++++++++++++++
Mwallet/src/main/res/values/strings.xml | 9++++++---
9 files changed, 325 insertions(+), 70 deletions(-)

diff --git a/wallet/src/main/java/net/taler/wallet/balances/BalanceManager.kt b/wallet/src/main/java/net/taler/wallet/balances/BalanceManager.kt @@ -58,6 +58,11 @@ sealed class BalanceState { data class Error( val error: TalerErrorInfo, ): BalanceState() + + fun showWelcome() = this is None || + (this is Success + && balances.isEmpty() + && donauSummary.isEmpty()) } // TODO: rename to AssetsManager diff --git a/wallet/src/main/java/net/taler/wallet/balances/BalancesComposable.kt b/wallet/src/main/java/net/taler/wallet/balances/BalancesComposable.kt @@ -20,15 +20,12 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.animateContentSize import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -37,7 +34,6 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight import androidx.compose.material3.Badge -import androidx.compose.material3.Button import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.ListItem @@ -47,11 +43,9 @@ import androidx.compose.material3.OutlinedCard import androidx.compose.material3.ProvideTextStyle import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import net.taler.common.Amount @@ -73,57 +67,62 @@ fun BalancesComposable( innerPadding: PaddingValues, state: BalanceState, devMode: Boolean, + networkStatus: Boolean, + onWithdrawMoneyClicked: () -> Unit, onGetDemoMoneyClicked: () -> Unit, onBalanceClicked: (balance: BalanceItem) -> Unit, onPendingClicked: (balance: BalanceItem) -> Unit, onStatementClicked: (host: String) -> Unit, ) { + if (state.showWelcome()) { + EmptyBalancesComposable( + innerPadding = innerPadding, + networkStatus = networkStatus, + onWithdrawMoneyClicked, + onGetDemoMoneyClicked, + ) + + return + } + when (state) { - is BalanceState.None -> {} is BalanceState.Loading -> LoadingScreen() is BalanceState.Error -> ErrorComposable(state.error, devMode = devMode, modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState())) - is BalanceState.Success -> if ( - state.balances.isNotEmpty() - || state.donauSummary.isNotEmpty()) { - LazyColumn( - Modifier - .consumeWindowInsets(innerPadding) - .fillMaxSize(), - contentPadding = innerPadding, - ) { - if (state.balances.isNotEmpty()) stickyHeader { - SectionHeader { Text(stringResource(R.string.assets_section_balances)) } - } + is BalanceState.Success -> LazyColumn( + Modifier + .consumeWindowInsets(innerPadding) + .fillMaxSize(), + contentPadding = innerPadding, + ) { + if (state.balances.isNotEmpty()) stickyHeader { + SectionHeader { Text(stringResource(R.string.assets_section_balances)) } + } - items(state.balances, key = { it.scopeInfo.hashCode() }) { balance -> - BalanceRow( - balance, - onClick = { onBalanceClicked(balance) }, - onPendingClick = { onPendingClicked(balance) }, - ) - } + items(state.balances, key = { it.scopeInfo.hashCode() }) { balance -> + BalanceRow( + balance, + onClick = { onBalanceClicked(balance) }, + onPendingClick = { onPendingClicked(balance) }, + ) + } - if (state.donauSummary.isNotEmpty()) stickyHeader { - SectionHeader { Text(stringResource(R.string.assets_section_statements)) } - } + if (state.donauSummary.isNotEmpty()) stickyHeader { + SectionHeader { Text(stringResource(R.string.assets_section_statements)) } + } - items(state.donauSummary) { statement -> - StatementRow( - statement, - onClick = { onStatementClicked(statement.donauBaseUrl) }, - ) - } + items(state.donauSummary) { statement -> + StatementRow( + statement, + onClick = { onStatementClicked(statement.donauBaseUrl) }, + ) } - } else { - EmptyBalancesComposable( - innerPadding = innerPadding, - onGetDemoMoneyClicked, - ) } + + else -> {} } } @@ -282,32 +281,6 @@ fun PendingComposable( ) } -@Composable -fun EmptyBalancesComposable( - innerPadding: PaddingValues, - onGetDemoMoneyClicked: () -> Unit, -) { - Column( - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center, - ) { - Text( - stringResource(R.string.balances_empty_state), - textAlign = TextAlign.Center, - style = MaterialTheme.typography.bodyMedium, - ) - - Spacer(Modifier.height(32.dp)) - - Button(onGetDemoMoneyClicked) { - Text(stringResource(R.string.balances_empty_get_money)) - } - } -} - @Preview @Composable fun BalancesComposablePreview() { @@ -350,6 +323,8 @@ fun BalancesComposablePreview() { innerPadding = PaddingValues(0.dp), state = BalanceState.Success(balances, donauSummary), devMode = false, + networkStatus = true, + onWithdrawMoneyClicked = {}, onGetDemoMoneyClicked = {}, onBalanceClicked = {}, onPendingClicked = {}, @@ -367,6 +342,8 @@ fun BalancesComposableErrorPreview() { state = BalanceState.Error(TalerErrorInfo .makeCustomError("Balances could not be loaded")), devMode = false, + networkStatus = false, + onWithdrawMoneyClicked = {}, onGetDemoMoneyClicked = {}, onBalanceClicked = {}, onPendingClicked = {}, @@ -383,6 +360,8 @@ fun BalancesComposableEmptyPreview() { innerPadding = PaddingValues(0.dp), state = BalanceState.Success(listOf(), listOf()), devMode = false, + networkStatus = false, + onWithdrawMoneyClicked = {}, onGetDemoMoneyClicked = {}, onBalanceClicked = {}, onPendingClicked = {}, diff --git a/wallet/src/main/java/net/taler/wallet/balances/EmptyBalancesComposable.kt b/wallet/src/main/java/net/taler/wallet/balances/EmptyBalancesComposable.kt @@ -0,0 +1,142 @@ +/* + * This file is part of GNU Taler + * (C) 2026 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.balances + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.only +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.systemBars +import androidx.compose.foundation.layout.windowInsetsPadding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.Button +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import net.taler.wallet.R +import net.taler.wallet.compose.Material3MenuGroup +import net.taler.wallet.compose.Material3MenuItemData + +@Composable +fun EmptyBalancesComposable( + innerPadding: PaddingValues, + networkStatus: Boolean, + onWithdrawMoneyClicked: () -> Unit, + onGetDemoMoneyClicked: () -> Unit, +) { + LazyColumn ( + modifier = Modifier + .padding(innerPadding) + .windowInsetsPadding(WindowInsets.systemBars.only( + WindowInsetsSides.Top + )) + .padding(horizontal = 16.dp) + .fillMaxSize(), + ) { + item { Spacer(Modifier.height(20.dp)) } + + item { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + Image( + modifier = Modifier + .height(45.dp) + .padding(end = 5.dp), + painter = painterResource(R.drawable.ic_taler_full), + contentDescription = null) + + Text( + stringResource(R.string.wallet), + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Medium, + ) + } + } + + item { Spacer(Modifier.height(20.dp)) } + + item { + Material3MenuGroup(buildList { + add(Material3MenuItemData( + title = { Text(stringResource(R.string.balances_empty_withdraw_chf_title)) }, + description = { + Column { + Text(stringResource(R.string.balances_empty_withdraw_chf_message)) + Spacer(Modifier.height(6.dp)) + Button( + modifier = Modifier.fillMaxWidth(), + onClick = onWithdrawMoneyClicked, + enabled = networkStatus, + ) { + Text( + color = MaterialTheme.colorScheme.onPrimary, + text = stringResource(R.string.balances_empty_withdraw_chf_button), + ) + } + } + }, + )) + }) + } + + item { Spacer(Modifier.height(12.dp)) } + + item { + Material3MenuGroup(buildList { + add( + Material3MenuItemData( + title = {}, + description = { + Column { + Text(stringResource(R.string.balances_empty_withdraw_kudos_message)) + Spacer(Modifier.height(6.dp)) + Button( + modifier = Modifier.fillMaxWidth(), + onClick = onGetDemoMoneyClicked, + enabled = networkStatus, + ) { + Text( + color = MaterialTheme.colorScheme.onPrimary, + text = stringResource(R.string.balances_empty_withdraw_kudos_button), + ) + } + } + }, + ) + ) + }) + } + } +} +\ No newline at end of file diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeManager.kt b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeManager.kt @@ -95,7 +95,7 @@ class ExchangeManager( return mExchanges } - fun add(exchangeUrl: String) = scope.launch { + fun add(exchangeUrl: String, onSuccess: (() -> Unit)? = null) = scope.launch { mProgress.value = true api.request<Unit>("addExchange") { put("allowCompletion", true) @@ -108,6 +108,7 @@ class ExchangeManager( mProgress.value = false Log.d(TAG, "Exchange $exchangeUrl added") list() + onSuccess?.invoke() } } diff --git a/wallet/src/main/java/net/taler/wallet/main/MainComposable.kt b/wallet/src/main/java/net/taler/wallet/main/MainComposable.kt @@ -33,6 +33,8 @@ fun MainComposable( txResult: TransactionsResult, viewMode: ViewMode, devMode: Boolean, + networkStatus: Boolean, + onWithdrawMoneyClicked: () -> Unit, onGetDemoMoneyClicked: () -> Unit, onBalanceClicked: (balance: BalanceItem) -> Unit, onPendingClicked: (balance: BalanceItem) -> Unit, @@ -46,6 +48,8 @@ fun MainComposable( innerPadding = innerPadding, state = state, devMode = devMode, + networkStatus = networkStatus, + onWithdrawMoneyClicked = onWithdrawMoneyClicked, onGetDemoMoneyClicked = onGetDemoMoneyClicked, onBalanceClicked = onBalanceClicked, onPendingClicked = onPendingClicked, diff --git a/wallet/src/main/java/net/taler/wallet/main/MainFragment.kt b/wallet/src/main/java/net/taler/wallet/main/MainFragment.kt @@ -94,6 +94,7 @@ class MainFragment: Fragment() { val context = LocalContext.current val online by model.networkManager.networkStatus.observeAsState(false) + val networkStatus by model.networkManager.networkStatus.observeAsState(false) val balanceState by model.balanceManager.state.observeAsState(BalanceState.None) val viewMode by model.viewMode.collectAsStateLifecycleAware() val devMode by model.devMode.observeAsState(false) @@ -152,6 +153,16 @@ class MainFragment: Fragment() { model.showAssets() } + LaunchedEffect(tab, balanceState, viewMode) { + (requireActivity() as AppCompatActivity).apply { + if (tab == Tab.ASSETS && viewMode is ViewMode.Assets && balanceState.showWelcome()) { + supportActionBar?.hide() + } else { + supportActionBar?.show() + } + } + } + when (tab) { Tab.ASSETS -> MainComposable( innerPadding = innerPadding, @@ -159,6 +170,14 @@ class MainFragment: Fragment() { txResult = txResult, viewMode = viewMode, devMode = devMode, + networkStatus = networkStatus, + onWithdrawMoneyClicked = { + // FIXME: remove exchange when whitelisted in wallet-core + model.exchangeManager.add("https://exchange.taler-ops.ch/") { + val args = bundleOf("exchangeBaseUrl" to "https://exchange.taler-ops.ch/") + findNavController().navigate(R.id.promptWithdraw, args) + } + }, onGetDemoMoneyClicked = { model.withdrawManager.withdrawTestBalance() Snackbar.make( @@ -261,6 +280,13 @@ class MainFragment: Fragment() { model.balanceManager.loadAssets(model.viewMode.value is ViewMode.Assets) } + override fun onDestroyView() { + super.onDestroyView() + (requireActivity() as AppCompatActivity).apply { + supportActionBar?.show() + } + } + private fun setTitle(tab: Tab, viewMode: ViewMode?) { (requireActivity() as AppCompatActivity).apply { supportActionBar?.title = when (tab) { diff --git a/wallet/src/main/res/drawable-night/ic_taler_full.xml b/wallet/src/main/res/drawable-night/ic_taler_full.xml @@ -0,0 +1,55 @@ +<!-- + ~ This file is part of GNU Taler + ~ (C) 2026 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/> + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="201dp" + android:height="90dp" + android:viewportWidth="201" + android:viewportHeight="90"> + <path + android:pathData="M86.66,1.12C102.25,1.12 115.79,10.52 122.62,24.32L116.81,24.32C110.49,13.62 99.35,6.52 86.66,6.52C66.97,6.52 51.01,23.63 51.01,44.74C51.01,55.07 54.83,64.44 61.05,71.32C59.71,72.44 58.28,73.45 56.77,74.33C50.07,66.55 45.97,56.16 45.97,44.74C45.97,20.65 64.19,1.12 86.66,1.12ZZM122.51,65.38C115.65,79.06 102.17,88.36 86.66,88.36C85.61,88.36 84.57,88.31 83.53,88.23C86.59,86.67 89.45,84.75 92.07,82.52C102.39,80.84 111.26,74.41 116.67,65.38Z" + android:strokeWidth="0.327943" + android:fillColor="#FFFFFF" + android:strokeColor="#00000000" + android:fillType="evenOdd"/> + <path + android:pathData="M64.21,1.12C65.26,1.12 66.31,1.16 67.34,1.25C64.29,2.81 61.43,4.73 58.8,6.96C41.68,9.75 28.56,25.6 28.56,44.74C28.56,59 35.85,71.44 46.65,78.01C45.06,78.28 43.43,78.42 41.76,78.42C40.52,78.42 39.3,78.33 38.1,78.18C29.19,70.18 23.52,58.17 23.52,44.74C23.52,20.65 41.74,1.12 64.21,1.12ZZM69.62,82.52C79.94,80.84 88.81,74.41 94.22,65.38L100.07,65.38C93.2,79.06 79.72,88.36 64.21,88.36C63.16,88.36 62.12,88.31 61.08,88.23C64.14,86.67 67,84.75 69.62,82.52ZZM94.36,24.32C91.22,19.01 86.89,14.58 81.77,11.47C83.36,11.2 85,11.06 86.66,11.06C87.9,11.06 89.12,11.14 90.33,11.29C94.34,14.9 97.7,19.32 100.18,24.32Z" + android:strokeWidth="0.327943" + android:fillColor="#FFFFFF" + android:strokeColor="#00000000" + android:fillType="evenOdd"/> + <path + android:pathData="M41.76,1.12C42.83,1.12 43.88,1.17 44.92,1.25C41.88,2.81 39.02,4.73 36.4,6.95C19.25,9.72 6.11,25.58 6.11,44.74C6.11,65.85 22.07,82.96 41.76,82.96C54.36,82.96 65.43,75.95 71.78,65.38L77.61,65.38C70.75,79.06 57.27,88.36 41.76,88.36C19.29,88.36 1.08,68.83 1.08,44.74C1.08,20.65 19.29,1.12 41.76,1.12ZZM71.9,24.32C70.59,22.1 69.07,20.04 67.38,18.16C68.72,17.04 70.15,16.03 71.65,15.15C74.03,17.9 76.07,20.98 77.72,24.32Z" + android:strokeWidth="0.327943" + android:fillColor="#FFFFFF" + android:strokeColor="#00000000" + android:fillType="evenOdd"/> + <path + android:pathData="M76.14,34.41L85.3,34.41L85.3,29.37L61.86,29.37L61.86,34.41L71.02,34.41L71.02,60.33L76.14,60.33Z" + android:fillColor="#FFFFFF"/> + <path + android:pathData="M92.65,52.86L106.31,52.86L109.24,60.33L114.6,60.33L101.89,29.15L97.19,29.15L84.48,60.33L89.68,60.33ZM104.45,48.03L94.5,48.03L99.46,35.65Z" + android:fillColor="#FFFFFF"/> + <path + android:pathData="M123.81,29.37L119.23,29.37L119.23,60.33L139.77,60.33L139.77,55.42C134.45,55.42 129.13,55.42 123.81,55.42Z" + android:fillColor="#FFFFFF"/> + <path + android:pathData="M166.47,29.37L145.1,29.37L145.1,60.33L166.68,60.33L166.68,55.42L150.13,55.42L150.13,47.15L164.62,47.15L164.62,42.24L150.13,42.24L150.13,34.28L166.47,34.28Z" + android:fillColor="#FFFFFF"/> + <path + android:pathData="M191.19,39.47C191.19,41.07 190.65,42.35 189.57,43.29C188.5,44.24 187.05,44.72 185.23,44.72L177.78,44.72L177.78,34.28L185.19,34.28C187.09,34.28 188.57,34.71 189.62,35.59C190.67,36.46 191.19,37.76 191.19,39.47ZZM197.26,60.33L189.46,48.61C190.48,48.31 191.4,47.89 192.24,47.35C193.08,46.8 193.8,46.14 194.41,45.36C195.01,44.58 195.49,43.68 195.83,42.66C196.18,41.64 196.35,40.48 196.35,39.19C196.35,37.68 196.1,36.32 195.61,35.1C195.11,33.87 194.4,32.84 193.48,32C192.56,31.16 191.43,30.51 190.1,30.05C188.76,29.59 187.27,29.37 185.62,29.37L172.74,29.37L172.74,60.33L177.78,60.33L177.78,49.54L184.15,49.54L191.27,60.33Z" + android:fillColor="#FFFFFF"/> +</vector> diff --git a/wallet/src/main/res/drawable/ic_taler_full.xml b/wallet/src/main/res/drawable/ic_taler_full.xml @@ -0,0 +1,39 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="670dp" + android:height="300dp" + android:viewportWidth="201" + android:viewportHeight="90"> + <path + android:pathData="m86.66,1.12c15.59,0 29.13,9.4 35.96,23.2h-5.82C110.49,13.62 99.35,6.52 86.66,6.52c-19.69,0 -35.65,17.11 -35.65,38.22 0,10.33 3.83,19.7 10.04,26.58 -1.34,1.12 -2.77,2.13 -4.28,3.01C50.07,66.55 45.97,56.16 45.97,44.74c0,-24.09 18.22,-43.62 40.69,-43.62zM122.51,65.38c-6.87,13.68 -20.35,22.98 -35.85,22.98 -1.05,0 -2.1,-0.04 -3.13,-0.13 3.05,-1.56 5.91,-3.48 8.54,-5.71 10.32,-1.68 19.19,-8.11 24.6,-17.15z" + android:strokeWidth="0.327943" + android:fillColor="#0042b3" + android:strokeColor="#00000000" + android:fillType="evenOdd"/> + <path + android:pathData="m64.21,1.12c1.05,0 2.1,0.04 3.13,0.13C64.29,2.81 61.43,4.73 58.8,6.96 41.68,9.75 28.56,25.6 28.56,44.74c0,14.26 7.29,26.7 18.09,33.27 -1.59,0.27 -3.23,0.41 -4.89,0.41 -1.24,0 -2.46,-0.08 -3.66,-0.23C29.19,70.18 23.53,58.17 23.53,44.74 23.53,20.65 41.74,1.12 64.21,1.12ZM69.62,82.52C79.94,80.84 88.81,74.41 94.22,65.38h5.84c-6.87,13.68 -20.35,22.98 -35.85,22.98 -1.05,0 -2.1,-0.04 -3.13,-0.13 3.05,-1.56 5.91,-3.48 8.54,-5.71zM94.36,24.32c-3.14,-5.31 -7.47,-9.74 -12.58,-12.85 1.59,-0.27 3.23,-0.41 4.89,-0.41 1.24,0 2.46,0.08 3.66,0.23 4.02,3.61 7.37,8.03 9.85,13.03z" + android:strokeWidth="0.327943" + android:fillColor="#0042b3" + android:strokeColor="#00000000" + android:fillType="evenOdd"/> + <path + android:pathData="m41.76,1.12c1.06,0 2.12,0.04 3.16,0.13 -3.05,1.56 -5.9,3.47 -8.52,5.7C19.25,9.72 6.11,25.58 6.11,44.74c0,21.11 15.96,38.22 35.65,38.22 12.6,0 23.67,-7.01 30.01,-17.58h5.84C70.75,79.06 57.27,88.36 41.76,88.36c-22.47,0 -40.69,-19.53 -40.69,-43.62 0,-24.09 18.22,-43.62 40.69,-43.62zM71.91,24.32c-1.31,-2.22 -2.83,-4.29 -4.53,-6.17 1.34,-1.12 2.77,-2.13 4.28,-3.01 2.37,2.75 4.42,5.83 6.07,9.17z" + android:strokeWidth="0.327943" + android:fillColor="#0042b3" + android:strokeColor="#00000000" + android:fillType="evenOdd"/> + <path + android:fillColor="#FF000000" + android:pathData="m76.14,34.41h9.16V29.37H61.86v5.04h9.16v25.92h5.12z"/> + <path + android:fillColor="#FF000000" + android:pathData="m92.65,52.86h13.66l2.93,7.48h5.36L101.89,29.14L97.19,29.14L84.48,60.33h5.2zM104.45,48.03h-9.94l4.95,-12.39z"/> + <path + android:fillColor="#FF000000" + android:pathData="m123.81,29.37h-4.58v30.97h20.55v-4.91c-5.32,0 -10.64,0 -15.97,0z"/> + <path + android:fillColor="#FF000000" + android:pathData="m166.47,29.37h-21.38v30.97h21.58v-4.91h-16.55v-8.27h14.48V42.24h-14.48v-7.96h16.34z"/> + <path + android:fillColor="#FF000000" + android:pathData="m191.19,39.47c0,1.6 -0.54,2.88 -1.62,3.82 -1.07,0.95 -2.52,1.42 -4.35,1.42h-7.45L177.78,34.28h7.41c1.91,0 3.38,0.44 4.43,1.31 1.05,0.87 1.57,2.17 1.57,3.89zM197.26,60.33 L189.46,48.61c1.02,-0.29 1.95,-0.71 2.79,-1.26 0.84,-0.55 1.56,-1.21 2.17,-1.99 0.61,-0.78 1.08,-1.68 1.42,-2.7 0.34,-1.02 0.52,-2.18 0.52,-3.47 0,-1.5 -0.25,-2.87 -0.74,-4.09 -0.5,-1.22 -1.2,-2.26 -2.12,-3.1 -0.92,-0.84 -2.05,-1.49 -3.38,-1.95 -1.33,-0.46 -2.83,-0.69 -4.48,-0.69h-12.88v30.97h5.03L177.78,49.54h6.38l7.12,10.79z"/> +</vector> diff --git a/wallet/src/main/res/values/strings.xml b/wallet/src/main/res/values/strings.xml @@ -82,6 +82,7 @@ GNU Taler is immune to many types of fraud such as credit card data theft, phish <string name="save">Save</string> <string name="share_payment">Share payment link</string> <string name="uri_invalid">Not a valid Taler link</string> + <string name="wallet">Wallet</string> <string name="warning">Warning</string> <!-- Biometric lock --> @@ -139,9 +140,11 @@ GNU Taler is immune to many types of fraud such as credit card data theft, phish <string name="balance_scope_auditor">Auditor: %1$s</string> <string name="balance_scope_exchange">From %1$s</string> - <string name="balances_empty_state">There is no digital cash in your wallet.\n\nYou can get demo money from the demo bank:\n\nhttps://bank.demo.taler.net</string> - <string name="balances_empty_demo_url">https://bank.demo.taler.net</string> - <string name="balances_empty_get_money">Get demo money</string> + <string name="balances_empty_withdraw_chf_title">Welcome to Taler Wallet!</string> + <string name="balances_empty_withdraw_chf_message">To make your first payment, withdraw digital cash.</string> + <string name="balances_empty_withdraw_chf_button">Withdraw CHF</string> + <string name="balances_empty_withdraw_kudos_message">Get demo cash to experience how to pay with the money of the future.</string> + <string name="balances_empty_withdraw_kudos_button">Get demo cash</string> <string name="balances_inbound_amount">+%1$s incoming</string> <string name="balances_outbound_amount">-%1$s outgoing</string>