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:
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>