gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-taler-ios] branch master updated (101ccb8 -> e082595)


From: gnunet
Subject: [taler-taler-ios] branch master updated (101ccb8 -> e082595)
Date: Mon, 06 Nov 2023 20:40:07 +0100

This is an automated email from the git hooks/post-receive script.

marc-stibane pushed a change to branch master
in repository taler-ios.

    from 101ccb8  Bump version to 0.9.3 (23)
     new b30e181  avoid unneccessary localizations
     new 8d63be2  until Xcode 15.1 is final
     new b7cd2c4  Purpose->Subject, cleanup
     new 6bf811b  No l10n for Debug
     new d84e4b1  logger
     new 11c1525  L10N
     new fa60cb7  IncompleteRowV
     new 3559d36  Accessibility
     new 370cbef  Logger
     new b6214e9  Use System Alert for iOS16+
     new b9cb956  cleanup
     new 1c8b9fd  KYC - wip
     new b4e57fd  Accessibility
     new 7c63571  Blue Logo
     new b6df844  cleanup sortedTransactions
     new 681ecf2  ManualDetailsV, minimal
     new 0f8fbb8  ThreeAmountsV cleanup
     new 0b63d48  Default for Sound & Haptics ON
     new 82b5427  SendDone: Prevent double execution
     new 03bb845  Debugging
     new 0fcd73c  Accessibility
     new a26ecb9  Announce
     new 63fa5d3  L10N, EMPTYSTRING
     new d9f33be  Accessibility: Contrast
     new e082595  Bump version to 0.9.3 (24)

The 25 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 TalerWallet.xcodeproj/project.pbxproj              |  52 +++----
 .../Contents.json                                  |   2 +-
 .../taler-logo-2023-blue.svg}                      |   2 +-
 TalerWallet1/Backend/WalletCore.swift              |  18 +--
 TalerWallet1/Controllers/Controller.swift          |   4 +-
 TalerWallet1/Controllers/DebugViewC.swift          |  83 +++++-----
 TalerWallet1/Controllers/PublicConstants.swift     |   1 +
 TalerWallet1/Controllers/TalerWallet1App.swift     |   4 +-
 TalerWallet1/Helper/LocalizedAlertError.swift      |   2 +-
 TalerWallet1/Helper/TalerDater.swift               |   6 +-
 TalerWallet1/Helper/WalletColors.swift             |   2 +-
 TalerWallet1/Model/Model+Transactions.swift        |   2 +-
 TalerWallet1/Model/Transaction.swift               |  19 +--
 TalerWallet1/Model/WalletModel.swift               |   2 +-
 TalerWallet1/Views/Balances/BalanceRowView.swift   |  35 +++--
 .../Views/Balances/BalancesSectionView.swift       |  42 ++---
 TalerWallet1/Views/Balances/IncompleteRowV.swift   |  39 +++++
 TalerWallet1/Views/Balances/PendingRowView.swift   |  22 ++-
 .../Views/Balances/UncompletedRowView.swift        |  34 ----
 TalerWallet1/Views/Exchange/ExchangeListView.swift | 108 +++++++------
 TalerWallet1/Views/Exchange/ExchangeRowView.swift  |  20 +--
 .../Views/Exchange/ExchangeSectionView.swift       |   1 -
 TalerWallet1/Views/Exchange/ManualWithdraw.swift   |   2 +-
 TalerWallet1/Views/Exchange/QuiteSomeCoins.swift   |   4 +-
 TalerWallet1/Views/HelperViews/AmountRowV.swift    |  16 +-
 TalerWallet1/Views/HelperViews/BarGraph.swift      |   2 +
 TalerWallet1/Views/HelperViews/Buttons.swift       | 171 +--------------------
 TalerWallet1/Views/HelperViews/CopyShare.swift     |   9 +-
 .../Views/HelperViews/LaunchAnimationView.swift    |   9 +-
 .../Views/HelperViews/QRCodeDetailView.swift       |   8 +-
 TalerWallet1/Views/HelperViews/SelectDays.swift    |  80 ++++++----
 .../Views/HelperViews/TextFieldAlert.swift         |   4 +
 .../Views/HelperViews/View+fitsSideBySide.swift    |   9 ++
 TalerWallet1/Views/Main/MainView.swift             |  61 ++++++--
 TalerWallet1/Views/Main/WalletEmptyView.swift      |   4 +-
 TalerWallet1/Views/Peer2peer/PaymentPurpose.swift  |  34 ++--
 TalerWallet1/Views/Peer2peer/RequestPayment.swift  |   2 +-
 .../Peer2peer/{SendDone.swift => SendDoneV.swift}  |  35 +++--
 TalerWallet1/Views/Peer2peer/SendPurpose.swift     |  38 +++--
 TalerWallet1/Views/Settings/AboutView.swift        |   1 +
 TalerWallet1/Views/Settings/SettingsItem.swift     |  58 ++++---
 TalerWallet1/Views/Settings/SettingsView.swift     |  71 +++++----
 .../Views/Sheets/P2P_Sheets/P2pPayURIView.swift    |  16 +-
 .../Sheets/P2P_Sheets/P2pReceiveURIView.swift      |  16 +-
 .../Views/Sheets/Payment/PayTemplateView.swift     |  32 ++--
 .../Views/Sheets/Payment/PaymentView.swift         |  32 ++--
 TalerWallet1/Views/Sheets/Sheet.swift              |   2 +
 .../WithdrawBankIntegrated/WithdrawURIView.swift   |  22 +--
 .../{ManualDetails.swift => ManualDetailsV.swift}  |  33 ++--
 .../{ThreeAmounts.swift => ThreeAmountsV.swift}    |  36 +++--
 .../Views/Transactions/TransactionDetailView.swift |  38 ++---
 .../Views/Transactions/TransactionRowView.swift    |   4 +-
 .../Views/Transactions/TransactionsListView.swift  |   1 +
 TestFlight/WhatToTest.en-US.txt                    |  10 ++
 54 files changed, 702 insertions(+), 658 deletions(-)
 copy TalerWallet1/Assets.xcassets/{taler-logo-2023-red.imageset => 
taler-logo-2023-blue.imageset}/Contents.json (72%)
 copy 
TalerWallet1/Assets.xcassets/{taler-logo-2023-red.imageset/taler-logo-2023-red.svg
 => taler-logo-2023-blue.imageset/taler-logo-2023-blue.svg} (92%)
 create mode 100644 TalerWallet1/Views/Balances/IncompleteRowV.swift
 delete mode 100644 TalerWallet1/Views/Balances/UncompletedRowView.swift
 rename TalerWallet1/Views/Peer2peer/{SendDone.swift => SendDoneV.swift} (81%)
 rename TalerWallet1/Views/Transactions/{ManualDetails.swift => 
ManualDetailsV.swift} (66%)
 rename TalerWallet1/Views/Transactions/{ThreeAmounts.swift => 
ThreeAmountsV.swift} (78%)

diff --git a/TalerWallet.xcodeproj/project.pbxproj 
b/TalerWallet.xcodeproj/project.pbxproj
index 485a9a7..83e73fd 100644
--- a/TalerWallet.xcodeproj/project.pbxproj
+++ b/TalerWallet.xcodeproj/project.pbxproj
@@ -42,7 +42,7 @@
                4E3EAE2D2A990778009F1BE8 /* Model+Exchange.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 4E3B4BC82A42BC4800CC88B8 /* 
Model+Exchange.swift */; };
                4E3EAE2E2A990778009F1BE8 /* QRCodeDetailView.swift in Sources 
*/ = {isa = PBXBuildFile; fileRef = 4E5A88F42A38A4FD00072618 /* 
QRCodeDetailView.swift */; };
                4E3EAE2F2A990778009F1BE8 /* TransactionsEmptyView.swift in 
Sources */ = {isa = PBXBuildFile; fileRef = 4E87C8722A31CB7F001C6406 /* 
TransactionsEmptyView.swift */; };
-               4E3EAE302A990778009F1BE8 /* UncompletedRowView.swift in Sources 
*/ = {isa = PBXBuildFile; fileRef = 4E87C8742A34B411001C6406 /* 
UncompletedRowView.swift */; };
+               4E3EAE302A990778009F1BE8 /* IncompleteRowV.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 4E87C8742A34B411001C6406 /* 
IncompleteRowV.swift */; };
                4E3EAE312A990778009F1BE8 /* SendAmount.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4E40E0BD29F25ABB00B85369 /* SendAmount.swift */; 
};
                4E3EAE332A990778009F1BE8 /* EqualIconWidthDomain.swift in 
Sources */ = {isa = PBXBuildFile; fileRef = 4E8E25322A1CD39700A27BFA /* 
EqualIconWidthDomain.swift */; };
                4E3EAE342A990778009F1BE8 /* SuperScriptDigits.swift in Sources 
*/ = {isa = PBXBuildFile; fileRef = 4EBA563E2A7FD9390084948B /* 
SuperScriptDigits.swift */; };
@@ -55,14 +55,14 @@
                4E3EAE3B2A990778009F1BE8 /* TalerWallet1App.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 4EB094EC298979620043A8A1 /* 
TalerWallet1App.swift */; };
                4E3EAE3C2A990778009F1BE8 /* WithdrawTOSView.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 4EB095402989CBFE0043A8A1 /* 
WithdrawTOSView.swift */; };
                4E3EAE3D2A990778009F1BE8 /* Sheet.swift in Sources */ = {isa = 
PBXBuildFile; fileRef = 4EEC157729F9032900D46A03 /* Sheet.swift */; };
-               4E3EAE3E2A990778009F1BE8 /* ManualDetails.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4E6EDD842A3615BE0031D520 /* ManualDetails.swift 
*/; };
+               4E3EAE3E2A990778009F1BE8 /* ManualDetailsV.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 4E6EDD842A3615BE0031D520 /* 
ManualDetailsV.swift */; };
                4E3EAE3F2A990778009F1BE8 /* View+dismissTop.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 4EB095082989CB7C0043A8A1 /* 
View+dismissTop.swift */; };
                4E3EAE402A990778009F1BE8 /* TransactionsListView.swift in 
Sources */ = {isa = PBXBuildFile; fileRef = 4EB0952F2989CBFE0043A8A1 /* 
TransactionsListView.swift */; };
                4E3EAE412A990778009F1BE8 /* WalletBackendRequest.swift in 
Sources */ = {isa = PBXBuildFile; fileRef = 4EB0951B2989CBCB0043A8A1 /* 
WalletBackendRequest.swift */; };
                4E3EAE422A990778009F1BE8 /* KeyboardResponder.swift in Sources 
*/ = {isa = PBXBuildFile; fileRef = 4EAD117529F672FA008EDD0B /* 
KeyboardResponder.swift */; };
                4E3EAE432A990778009F1BE8 /* TransactionRowView.swift in Sources 
*/ = {isa = PBXBuildFile; fileRef = 4EB095302989CBFE0043A8A1 /* 
TransactionRowView.swift */; };
                4E3EAE442A990778009F1BE8 /* PublicConstants.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 4EA1ABBD29A3833A008821EA /* 
PublicConstants.swift */; };
-               4E3EAE452A990778009F1BE8 /* SendDone.swift in Sources */ = {isa 
= PBXBuildFile; fileRef = 4EB3136029FEE79B007D68BC /* SendDone.swift */; };
+               4E3EAE452A990778009F1BE8 /* SendDoneV.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4EB3136029FEE79B007D68BC /* SendDoneV.swift */; 
};
                4E3EAE462A990778009F1BE8 /* TextFieldAlert.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 4EB095482989CBFE0043A8A1 /* 
TextFieldAlert.swift */; };
                4E3EAE472A990778009F1BE8 /* QuiteSomeCoins.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 4EBA82AC2A3F580500E5F39A /* 
QuiteSomeCoins.swift */; };
                4E3EAE482A990778009F1BE8 /* PayTemplateView.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 4EBA56402A7FF5200084948B /* 
PayTemplateView.swift */; };
@@ -99,7 +99,7 @@
                4E3EAE672A990778009F1BE8 /* PendingOpsListView.swift in Sources 
*/ = {isa = PBXBuildFile; fileRef = 4EB0954E2989CBFE0043A8A1 /* 
PendingOpsListView.swift */; };
                4E3EAE682A990778009F1BE8 /* WalletModel.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4EB095112989CBB00043A8A1 /* WalletModel.swift 
*/; };
                4E3EAE692A990778009F1BE8 /* URLSheet.swift in Sources */ = {isa 
= PBXBuildFile; fileRef = 4EB095332989CBFE0043A8A1 /* URLSheet.swift */; };
-               4E3EAE6A2A990778009F1BE8 /* ThreeAmounts.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4ED2F94A2A278F5100453B40 /* ThreeAmounts.swift 
*/; };
+               4E3EAE6A2A990778009F1BE8 /* ThreeAmountsV.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4ED2F94A2A278F5100453B40 /* ThreeAmountsV.swift 
*/; };
                4E3EAE6B2A990778009F1BE8 /* Model+Withdraw.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 4EB0953D2989CBFE0043A8A1 /* 
Model+Withdraw.swift */; };
                4E3EAE6C2A990778009F1BE8 /* ExchangeSectionView.swift in 
Sources */ = {isa = PBXBuildFile; fileRef = 4EC90C772A1B528B0071DC58 /* 
ExchangeSectionView.swift */; };
                4E3EAE6D2A990778009F1BE8 /* SendPurpose.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4E7940DD29FC307C00A9AEA1 /* SendPurpose.swift 
*/; };
@@ -153,13 +153,13 @@
                4E605DB82AB05E48002FB9A7 /* View+flippedDirection.swift in 
Sources */ = {isa = PBXBuildFile; fileRef = 4E605DB62AB05E48002FB9A7 /* 
View+flippedDirection.swift */; };
                4E605DBA2AB05FB6002FB9A7 /* BarGraph.swift in Sources */ = {isa 
= PBXBuildFile; fileRef = 4E605DB92AB05FB6002FB9A7 /* BarGraph.swift */; };
                4E605DBB2AB05FB6002FB9A7 /* BarGraph.swift in Sources */ = {isa 
= PBXBuildFile; fileRef = 4E605DB92AB05FB6002FB9A7 /* BarGraph.swift */; };
-               4E6EDD852A3615BE0031D520 /* ManualDetails.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4E6EDD842A3615BE0031D520 /* ManualDetails.swift 
*/; };
+               4E6EDD852A3615BE0031D520 /* ManualDetailsV.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 4E6EDD842A3615BE0031D520 /* 
ManualDetailsV.swift */; };
                4E6EDD872A363D8D0031D520 /* ListStyle.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4E6EDD862A363D8D0031D520 /* ListStyle.swift */; 
};
                4E753A062A0952F8002D9328 /* DebugViewC.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4E753A052A0952F7002D9328 /* DebugViewC.swift */; 
};
                4E753A082A0B6A5F002D9328 /* ShareSheet.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4E753A072A0B6A5F002D9328 /* ShareSheet.swift */; 
};
                4E7940DE29FC307C00A9AEA1 /* SendPurpose.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4E7940DD29FC307C00A9AEA1 /* SendPurpose.swift 
*/; };
                4E87C8732A31CB7F001C6406 /* TransactionsEmptyView.swift in 
Sources */ = {isa = PBXBuildFile; fileRef = 4E87C8722A31CB7F001C6406 /* 
TransactionsEmptyView.swift */; };
-               4E87C8752A34B411001C6406 /* UncompletedRowView.swift in Sources 
*/ = {isa = PBXBuildFile; fileRef = 4E87C8742A34B411001C6406 /* 
UncompletedRowView.swift */; };
+               4E87C8752A34B411001C6406 /* IncompleteRowV.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 4E87C8742A34B411001C6406 /* 
IncompleteRowV.swift */; };
                4E8C17202A6509BB005B2392 /* 
Atkinson-Hyperlegible-Regular-102.otf in Resources */ = {isa = PBXBuildFile; 
fileRef = 4E8C171C2A6509BB005B2392 /* Atkinson-Hyperlegible-Regular-102.otf */; 
};
                4E8C17212A6509BB005B2392 /* 
Atkinson-Hyperlegible-Italic-102.otf in Resources */ = {isa = PBXBuildFile; 
fileRef = 4E8C171D2A6509BB005B2392 /* Atkinson-Hyperlegible-Italic-102.otf */; 
};
                4E8C17222A6509BB005B2392 /* Atkinson-Hyperlegible-Bold-102.otf 
in Resources */ = {isa = PBXBuildFile; fileRef = 4E8C171E2A6509BB005B2392 /* 
Atkinson-Hyperlegible-Bold-102.otf */; };
@@ -227,7 +227,7 @@
                4EB0956E2989CBFE0043A8A1 /* Model+Pending.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4EB0954C2989CBFE0043A8A1 /* Model+Pending.swift 
*/; };
                4EB0956F2989CBFE0043A8A1 /* PendingOpView.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4EB0954D2989CBFE0043A8A1 /* PendingOpView.swift 
*/; };
                4EB095702989CBFE0043A8A1 /* PendingOpsListView.swift in Sources 
*/ = {isa = PBXBuildFile; fileRef = 4EB0954E2989CBFE0043A8A1 /* 
PendingOpsListView.swift */; };
-               4EB3136129FEE79B007D68BC /* SendDone.swift in Sources */ = {isa 
= PBXBuildFile; fileRef = 4EB3136029FEE79B007D68BC /* SendDone.swift */; };
+               4EB3136129FEE79B007D68BC /* SendDoneV.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4EB3136029FEE79B007D68BC /* SendDoneV.swift */; 
};
                4EB431672A1E55C700C5690E /* ManualWithdrawDone.swift in Sources 
*/ = {isa = PBXBuildFile; fileRef = 4EB431662A1E55C700C5690E /* 
ManualWithdrawDone.swift */; };
                4EBA563F2A7FD9390084948B /* SuperScriptDigits.swift in Sources 
*/ = {isa = PBXBuildFile; fileRef = 4EBA563E2A7FD9390084948B /* 
SuperScriptDigits.swift */; };
                4EBA56412A7FF5200084948B /* PayTemplateView.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 4EBA56402A7FF5200084948B /* 
PayTemplateView.swift */; };
@@ -242,7 +242,7 @@
                4EC90C782A1B528B0071DC58 /* ExchangeSectionView.swift in 
Sources */ = {isa = PBXBuildFile; fileRef = 4EC90C772A1B528B0071DC58 /* 
ExchangeSectionView.swift */; };
                4ECB62802A0BA6DF004ABBB7 /* Model+P2P.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4ECB627F2A0BA6DF004ABBB7 /* Model+P2P.swift */; 
};
                4ECB62822A0BB01D004ABBB7 /* SelectDays.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4ECB62812A0BB01D004ABBB7 /* SelectDays.swift */; 
};
-               4ED2F94B2A278F5100453B40 /* ThreeAmounts.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4ED2F94A2A278F5100453B40 /* ThreeAmounts.swift 
*/; };
+               4ED2F94B2A278F5100453B40 /* ThreeAmountsV.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4ED2F94A2A278F5100453B40 /* ThreeAmountsV.swift 
*/; };
                4EDBDCD92AB787CB00925C02 /* CallStack.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4EDBDCD82AB787CB00925C02 /* CallStack.swift */; 
};
                4EDBDCDA2AB787CB00925C02 /* CallStack.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4EDBDCD82AB787CB00925C02 /* CallStack.swift */; 
};
                4EEC157329F8242800D46A03 /* QRGeneratorView.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 4EEC157229F8242800D46A03 /* 
QRGeneratorView.swift */; };
@@ -328,7 +328,7 @@
                4E605DAE2AADDD13002FB9A7 /* UIScreen+screenSize.swift */ = {isa 
= PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; 
path = "UIScreen+screenSize.swift"; sourceTree = "<group>"; };
                4E605DB62AB05E48002FB9A7 /* View+flippedDirection.swift */ = 
{isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = 
sourcecode.swift; path = "View+flippedDirection.swift"; sourceTree = "<group>"; 
};
                4E605DB92AB05FB6002FB9A7 /* BarGraph.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= BarGraph.swift; sourceTree = "<group>"; };
-               4E6EDD842A3615BE0031D520 /* ManualDetails.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= ManualDetails.swift; sourceTree = "<group>"; };
+               4E6EDD842A3615BE0031D520 /* ManualDetailsV.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= ManualDetailsV.swift; sourceTree = "<group>"; };
                4E6EDD862A363D8D0031D520 /* ListStyle.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= ListStyle.swift; sourceTree = "<group>"; };
                4E753A042A08E720002D9328 /* transactions.json */ = {isa = 
PBXFileReference; lastKnownFileType = text.json; path = transactions.json; 
sourceTree = "<group>"; };
                4E753A052A0952F7002D9328 /* DebugViewC.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= DebugViewC.swift; sourceTree = "<group>"; };
@@ -336,7 +336,7 @@
                4E7940DD29FC307C00A9AEA1 /* SendPurpose.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= SendPurpose.swift; sourceTree = "<group>"; };
                4E7CFD372A532CE100CBAFF3 /* WhatToTest.en-US.txt */ = {isa = 
PBXFileReference; lastKnownFileType = text; path = "WhatToTest.en-US.txt"; 
sourceTree = "<group>"; };
                4E87C8722A31CB7F001C6406 /* TransactionsEmptyView.swift */ = 
{isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = 
sourcecode.swift; path = TransactionsEmptyView.swift; sourceTree = "<group>"; };
-               4E87C8742A34B411001C6406 /* UncompletedRowView.swift */ = {isa 
= PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; 
path = UncompletedRowView.swift; sourceTree = "<group>"; };
+               4E87C8742A34B411001C6406 /* IncompleteRowV.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= IncompleteRowV.swift; sourceTree = "<group>"; };
                4E8C171C2A6509BB005B2392 /* 
Atkinson-Hyperlegible-Regular-102.otf */ = {isa = PBXFileReference; 
lastKnownFileType = file; path = "Atkinson-Hyperlegible-Regular-102.otf"; 
sourceTree = "<group>"; };
                4E8C171D2A6509BB005B2392 /* 
Atkinson-Hyperlegible-Italic-102.otf */ = {isa = PBXFileReference; 
lastKnownFileType = file; path = "Atkinson-Hyperlegible-Italic-102.otf"; 
sourceTree = "<group>"; };
                4E8C171E2A6509BB005B2392 /* Atkinson-Hyperlegible-Bold-102.otf 
*/ = {isa = PBXFileReference; lastKnownFileType = file; path = 
"Atkinson-Hyperlegible-Bold-102.otf"; sourceTree = "<group>"; };
@@ -402,7 +402,7 @@
                4EB0954C2989CBFE0043A8A1 /* Model+Pending.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= "Model+Pending.swift"; sourceTree = "<group>"; };
                4EB0954D2989CBFE0043A8A1 /* PendingOpView.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= PendingOpView.swift; sourceTree = "<group>"; };
                4EB0954E2989CBFE0043A8A1 /* PendingOpsListView.swift */ = {isa 
= PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; 
path = PendingOpsListView.swift; sourceTree = "<group>"; };
-               4EB3136029FEE79B007D68BC /* SendDone.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= SendDone.swift; sourceTree = "<group>"; };
+               4EB3136029FEE79B007D68BC /* SendDoneV.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= SendDoneV.swift; sourceTree = "<group>"; };
                4EB431662A1E55C700C5690E /* ManualWithdrawDone.swift */ = {isa 
= PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
ManualWithdrawDone.swift; sourceTree = "<group>"; };
                4EBA563E2A7FD9390084948B /* SuperScriptDigits.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
SuperScriptDigits.swift; sourceTree = "<group>"; };
                4EBA56402A7FF5200084948B /* PayTemplateView.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= PayTemplateView.swift; sourceTree = "<group>"; };
@@ -414,7 +414,7 @@
                4EC90C772A1B528B0071DC58 /* ExchangeSectionView.swift */ = {isa 
= PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; 
path = ExchangeSectionView.swift; sourceTree = "<group>"; };
                4ECB627F2A0BA6DF004ABBB7 /* Model+P2P.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= "Model+P2P.swift"; sourceTree = "<group>"; };
                4ECB62812A0BB01D004ABBB7 /* SelectDays.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= SelectDays.swift; sourceTree = "<group>"; };
-               4ED2F94A2A278F5100453B40 /* ThreeAmounts.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= ThreeAmounts.swift; sourceTree = "<group>"; };
+               4ED2F94A2A278F5100453B40 /* ThreeAmountsV.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= ThreeAmountsV.swift; sourceTree = "<group>"; };
                4EDBDCD82AB787CB00925C02 /* CallStack.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= CallStack.swift; sourceTree = "<group>"; };
                4EEC157229F8242800D46A03 /* QRGeneratorView.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= QRGeneratorView.swift; sourceTree = "<group>"; };
                4EEC157729F9032900D46A03 /* Sheet.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= Sheet.swift; sourceTree = "<group>"; };
@@ -692,8 +692,8 @@
                                4EB095302989CBFE0043A8A1 /* 
TransactionRowView.swift */,
                                4EB095312989CBFE0043A8A1 /* 
TransactionDetailView.swift */,
                                4E87C8722A31CB7F001C6406 /* 
TransactionsEmptyView.swift */,
-                               4E6EDD842A3615BE0031D520 /* ManualDetails.swift 
*/,
-                               4ED2F94A2A278F5100453B40 /* ThreeAmounts.swift 
*/,
+                               4E6EDD842A3615BE0031D520 /* 
ManualDetailsV.swift */,
+                               4ED2F94A2A278F5100453B40 /* ThreeAmountsV.swift 
*/,
                        );
                        path = Transactions;
                        sourceTree = "<group>";
@@ -706,7 +706,7 @@
                                4EB095362989CBFE0043A8A1 /* 
BalanceRowView.swift */,
                                4EB065432A4CD1A80039B91D /* TwoRowButtons.swift 
*/,
                                4EB095382989CBFE0043A8A1 /* 
PendingRowView.swift */,
-                               4E87C8742A34B411001C6406 /* 
UncompletedRowView.swift */,
+                               4E87C8742A34B411001C6406 /* 
IncompleteRowV.swift */,
                        );
                        path = Balances;
                        sourceTree = "<group>";
@@ -773,7 +773,7 @@
                        children = (
                                4E40E0BD29F25ABB00B85369 /* SendAmount.swift */,
                                4E7940DD29FC307C00A9AEA1 /* SendPurpose.swift 
*/,
-                               4EB3136029FEE79B007D68BC /* SendDone.swift */,
+                               4EB3136029FEE79B007D68BC /* SendDoneV.swift */,
                                4E9320442A1645B600A87B0E /* 
RequestPayment.swift */,
                                4E9320462A164BC700A87B0E /* 
PaymentPurpose.swift */,
                        );
@@ -1064,7 +1064,7 @@
                                4E3EAE2D2A990778009F1BE8 /* 
Model+Exchange.swift in Sources */,
                                4E3EAE2E2A990778009F1BE8 /* 
QRCodeDetailView.swift in Sources */,
                                4E3EAE2F2A990778009F1BE8 /* 
TransactionsEmptyView.swift in Sources */,
-                               4E3EAE302A990778009F1BE8 /* 
UncompletedRowView.swift in Sources */,
+                               4E3EAE302A990778009F1BE8 /* 
IncompleteRowV.swift in Sources */,
                                4E605DAF2AADDD13002FB9A7 /* 
UIScreen+screenSize.swift in Sources */,
                                4E3EAE312A990778009F1BE8 /* SendAmount.swift in 
Sources */,
                                4E3EAE332A990778009F1BE8 /* 
EqualIconWidthDomain.swift in Sources */,
@@ -1078,14 +1078,14 @@
                                4E3EAE3B2A990778009F1BE8 /* 
TalerWallet1App.swift in Sources */,
                                4E3EAE3C2A990778009F1BE8 /* 
WithdrawTOSView.swift in Sources */,
                                4E3EAE3D2A990778009F1BE8 /* Sheet.swift in 
Sources */,
-                               4E3EAE3E2A990778009F1BE8 /* ManualDetails.swift 
in Sources */,
+                               4E3EAE3E2A990778009F1BE8 /* 
ManualDetailsV.swift in Sources */,
                                4E3EAE3F2A990778009F1BE8 /* 
View+dismissTop.swift in Sources */,
                                4E3EAE402A990778009F1BE8 /* 
TransactionsListView.swift in Sources */,
                                4E3EAE412A990778009F1BE8 /* 
WalletBackendRequest.swift in Sources */,
                                4E3EAE422A990778009F1BE8 /* 
KeyboardResponder.swift in Sources */,
                                4E3EAE432A990778009F1BE8 /* 
TransactionRowView.swift in Sources */,
                                4E3EAE442A990778009F1BE8 /* 
PublicConstants.swift in Sources */,
-                               4E3EAE452A990778009F1BE8 /* SendDone.swift in 
Sources */,
+                               4E3EAE452A990778009F1BE8 /* SendDoneV.swift in 
Sources */,
                                4E3EAE462A990778009F1BE8 /* 
TextFieldAlert.swift in Sources */,
                                4E3EAE472A990778009F1BE8 /* 
QuiteSomeCoins.swift in Sources */,
                                4E3EAE482A990778009F1BE8 /* 
PayTemplateView.swift in Sources */,
@@ -1128,7 +1128,7 @@
                                4E3EAE672A990778009F1BE8 /* 
PendingOpsListView.swift in Sources */,
                                4E3EAE682A990778009F1BE8 /* WalletModel.swift 
in Sources */,
                                4E3EAE692A990778009F1BE8 /* URLSheet.swift in 
Sources */,
-                               4E3EAE6A2A990778009F1BE8 /* ThreeAmounts.swift 
in Sources */,
+                               4E3EAE6A2A990778009F1BE8 /* ThreeAmountsV.swift 
in Sources */,
                                4E3EAE6B2A990778009F1BE8 /* 
Model+Withdraw.swift in Sources */,
                                4E3EAE6C2A990778009F1BE8 /* 
ExchangeSectionView.swift in Sources */,
                                4E3EAE6D2A990778009F1BE8 /* SendPurpose.swift 
in Sources */,
@@ -1173,7 +1173,7 @@
                                4E3B4BC92A42BC4800CC88B8 /* 
Model+Exchange.swift in Sources */,
                                4E5A88F52A38A4FD00072618 /* 
QRCodeDetailView.swift in Sources */,
                                4E87C8732A31CB7F001C6406 /* 
TransactionsEmptyView.swift in Sources */,
-                               4E87C8752A34B411001C6406 /* 
UncompletedRowView.swift in Sources */,
+                               4E87C8752A34B411001C6406 /* 
IncompleteRowV.swift in Sources */,
                                4E605DB02AADDD13002FB9A7 /* 
UIScreen+screenSize.swift in Sources */,
                                4E40E0BE29F25ABB00B85369 /* SendAmount.swift in 
Sources */,
                                4E8E25332A1CD39700A27BFA /* 
EqualIconWidthDomain.swift in Sources */,
@@ -1187,14 +1187,14 @@
                                4EB094ED298979620043A8A1 /* 
TalerWallet1App.swift in Sources */,
                                4EB095652989CBFE0043A8A1 /* 
WithdrawTOSView.swift in Sources */,
                                4EEC157829F9032900D46A03 /* Sheet.swift in 
Sources */,
-                               4E6EDD852A3615BE0031D520 /* ManualDetails.swift 
in Sources */,
+                               4E6EDD852A3615BE0031D520 /* 
ManualDetailsV.swift in Sources */,
                                4EB0950B2989CB7C0043A8A1 /* 
View+dismissTop.swift in Sources */,
                                4EB095562989CBFE0043A8A1 /* 
TransactionsListView.swift in Sources */,
                                4EB0951F2989CBCB0043A8A1 /* 
WalletBackendRequest.swift in Sources */,
                                4EAD117629F672FA008EDD0B /* 
KeyboardResponder.swift in Sources */,
                                4EB095572989CBFE0043A8A1 /* 
TransactionRowView.swift in Sources */,
                                4EA1ABBE29A3833A008821EA /* 
PublicConstants.swift in Sources */,
-                               4EB3136129FEE79B007D68BC /* SendDone.swift in 
Sources */,
+                               4EB3136129FEE79B007D68BC /* SendDoneV.swift in 
Sources */,
                                4EB0956B2989CBFE0043A8A1 /* 
TextFieldAlert.swift in Sources */,
                                4EBA82AD2A3F580500E5F39A /* 
QuiteSomeCoins.swift in Sources */,
                                4EBA56412A7FF5200084948B /* 
PayTemplateView.swift in Sources */,
@@ -1237,7 +1237,7 @@
                                4EB095702989CBFE0043A8A1 /* 
PendingOpsListView.swift in Sources */,
                                4EB095162989CBB00043A8A1 /* WalletModel.swift 
in Sources */,
                                4EB0955A2989CBFE0043A8A1 /* URLSheet.swift in 
Sources */,
-                               4ED2F94B2A278F5100453B40 /* ThreeAmounts.swift 
in Sources */,
+                               4ED2F94B2A278F5100453B40 /* ThreeAmountsV.swift 
in Sources */,
                                4EB095622989CBFE0043A8A1 /* 
Model+Withdraw.swift in Sources */,
                                4EC90C782A1B528B0071DC58 /* 
ExchangeSectionView.swift in Sources */,
                                4E7940DE29FC307C00A9AEA1 /* SendPurpose.swift 
in Sources */,
@@ -1496,7 +1496,7 @@
                                CODE_SIGN_ENTITLEMENTS = 
"$(TARGET_NAME).entitlements";
                                CODE_SIGN_IDENTITY = "Apple Development";
                                CODE_SIGN_STYLE = Automatic;
-                               CURRENT_PROJECT_VERSION = 23;
+                               CURRENT_PROJECT_VERSION = 24;
                                DEVELOPMENT_TEAM = GUDDQ9428Y;
                                ENABLE_PREVIEWS = YES;
                                GENERATE_INFOPLIST_FILE = YES;
@@ -1538,7 +1538,7 @@
                                CODE_SIGN_ENTITLEMENTS = 
"$(TARGET_NAME).entitlements";
                                CODE_SIGN_IDENTITY = "Apple Development";
                                CODE_SIGN_STYLE = Automatic;
-                               CURRENT_PROJECT_VERSION = 23;
+                               CURRENT_PROJECT_VERSION = 24;
                                DEVELOPMENT_TEAM = GUDDQ9428Y;
                                ENABLE_PREVIEWS = YES;
                                GENERATE_INFOPLIST_FILE = YES;
diff --git 
a/TalerWallet1/Assets.xcassets/taler-logo-2023-red.imageset/Contents.json 
b/TalerWallet1/Assets.xcassets/taler-logo-2023-blue.imageset/Contents.json
similarity index 72%
copy from 
TalerWallet1/Assets.xcassets/taler-logo-2023-red.imageset/Contents.json
copy to TalerWallet1/Assets.xcassets/taler-logo-2023-blue.imageset/Contents.json
index 50ee748..a10ccf1 100644
--- a/TalerWallet1/Assets.xcassets/taler-logo-2023-red.imageset/Contents.json
+++ b/TalerWallet1/Assets.xcassets/taler-logo-2023-blue.imageset/Contents.json
@@ -1,7 +1,7 @@
 {
   "images" : [
     {
-      "filename" : "taler-logo-2023-red.svg",
+      "filename" : "taler-logo-2023-blue.svg",
       "idiom" : "universal"
     },
   ],
diff --git 
a/TalerWallet1/Assets.xcassets/taler-logo-2023-red.imageset/taler-logo-2023-red.svg
 
b/TalerWallet1/Assets.xcassets/taler-logo-2023-blue.imageset/taler-logo-2023-blue.svg
similarity index 92%
copy from 
TalerWallet1/Assets.xcassets/taler-logo-2023-red.imageset/taler-logo-2023-red.svg
copy to 
TalerWallet1/Assets.xcassets/taler-logo-2023-blue.imageset/taler-logo-2023-blue.svg
index 3820d36..b6d9918 100644
--- 
a/TalerWallet1/Assets.xcassets/taler-logo-2023-red.imageset/taler-logo-2023-red.svg
+++ 
b/TalerWallet1/Assets.xcassets/taler-logo-2023-blue.imageset/taler-logo-2023-blue.svg
@@ -1,5 +1,5 @@
 <svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg";>
-<g id="aa" style="fill:red;fill-rule:evenodd">
+<g id="aa" style="fill:blue;fill-rule:evenodd">
 <!-- 90% -->
 <path d="M57.6 43.4
 c-25.5 4.3-44.9 28-44.9 56.5 0 31.5 23.9 57.2 53.3 57.2
diff --git a/TalerWallet1/Backend/WalletCore.swift 
b/TalerWallet1/Backend/WalletCore.swift
index 8fd3c18..3a02aaf 100644
--- a/TalerWallet1/Backend/WalletCore.swift
+++ b/TalerWallet1/Backend/WalletCore.swift
@@ -190,14 +190,19 @@ extension WalletCore {
                     if let type = TransactionType(rawValue: components[1]) {
                         guard type != .refresh else { return }
                         if decoded.newTxState.major == .done {
+                            logger.log("Done: \(decoded.transactionId, 
privacy: .private(mask: .hash))")
                             Controller.shared.playSound(type.isIncoming ? 2 : 
1)
                         } else if decoded.newTxState.major == .expired {
+                            logger.log("Expired: \(decoded.transactionId, 
privacy: .private(mask: .hash))")
                             Controller.shared.playSound(0)
                         }
                         postNotification(.TransactionStateTransition,
                                          userInfo: [TRANSACTIONTRANSITION: 
decoded])
                     }
                 }
+            } else {
+                // TODO: Same state usually means that an error is transmitted
+                logger.log("No State change: \(decoded.transactionId, privacy: 
.private(mask: .hash))")
             }
         } catch {       // rethrows
             symLog.log(jsonData)       // TODO: .error
@@ -237,16 +242,9 @@ extension WalletCore {
                     postNotification(.ProposalDownloaded, userInfo: nil)
 
                     // TODO: remove these once wallet-core doesn't send them 
anymore
-//                case "reserve-registered-with-bank":
-//                    symLog.log(anyPayload)
-//                case "withdraw-group-finished",
-//                     "pay-operation-success",
-//                     "withdrawal-group-bank-confirmed",          // replaced 
by transaction-state-transition
-//                     "withdrawal-group-reserve-ready",
-//                     "waiting-for-retry",                        // Bla Bla 
Bla
-                case "refresh-started", "refresh-melted",
-                     "refresh-revealed", "refresh-unwarranted":
-                    break
+//                case "refresh-started", "refresh-melted",
+//                     "refresh-revealed", "refresh-unwarranted":
+//                    break
                 default:
 print("\n❗️ WalletCore.swift:251 Notification: ", anyPayload, "\n")        // 
this is a new notification I haven't seen before
                     break
diff --git a/TalerWallet1/Controllers/Controller.swift 
b/TalerWallet1/Controllers/Controller.swift
index 788438c..fe55625 100644
--- a/TalerWallet1/Controllers/Controller.swift
+++ b/TalerWallet1/Controllers/Controller.swift
@@ -34,8 +34,8 @@ class Controller: ObservableObject {
 
     @Published var backendState: BackendState = .none       // only used for 
launch animation
     @Published var currencyInfos: [CurrencyInfo]
-    @AppStorage("useHaptics") var useHaptics: Bool = false  // extension 
mustn't define this, so it must be here
-    @AppStorage("playSounds") var playSounds: Int = 0       // extension 
mustn't define this, so it must be here
+    @AppStorage("useHaptics") var useHaptics: Bool = true   // extension 
mustn't define this, so it must be here
+    @AppStorage("playSounds") var playSounds: Int = 1       // extension 
mustn't define this, so it must be here
     @AppStorage("talerFont") var talerFont: Int = 0         // extension 
mustn't define this, so it must be here
     let hapticCapability = CHHapticEngine.capabilitiesForHardware()
     let logger = Logger(subsystem: "net.taler.gnu", category: "Controller")
diff --git a/TalerWallet1/Controllers/DebugViewC.swift 
b/TalerWallet1/Controllers/DebugViewC.swift
index bf73067..50cbdca 100644
--- a/TalerWallet1/Controllers/DebugViewC.swift
+++ b/TalerWallet1/Controllers/DebugViewC.swift
@@ -39,7 +39,7 @@ public let VIEW_TRANSACTIONDETAIL = VIEW_TRANSACTIONLIST + 1  
      // 21 Transa
 
 
 // MARK: - Manual Withdrawal (from ExchangeList)
-// receive coins from bank ==> shows IBAN + Purpose for manual wire transfer
+// receive coins from bank ==> shows IBAN + Purpose/Subject for manual wire 
transfer
 public let VIEW_WITHDRAWAL = VIEW_TRANSACTIONLIST + 10              // 30 
WithdrawAmount
 public let VIEW_WITHDRAW_TOS = VIEW_WITHDRAWAL + 1                  // 31 
WithdrawTOSView
 public let VIEW_WITHDRAW_ACCEPT = VIEW_WITHDRAW_TOS + 1             // 32
@@ -47,27 +47,26 @@ public let VIEW_WITHDRAW_ACCEPT = VIEW_WITHDRAW_TOS + 1     
        // 32
 // MARK: Manual Deposit (from ExchangeList)
 // send coins back to bank account ==> orders exchange to make the wire 
transfer
 public let VIEW_DEPOSIT = VIEW_WITHDRAWAL + 10                      // 40 
Deposit Coins
-//public let VIEW_DEPOSIT_TOS                                       // 41 - 
user already accepted the ToS at withdrawal, invoice or receive
+//public let VIEW_DEPOSIT_TOS                                       // - user 
already accepted the ToS at withdrawal, invoice or receive
 public let VIEW_DEPOSIT_ACCEPT = VIEW_DEPOSIT + 2                   // 42
 
 // MARK: P2P Send Coins (from Balances)
 // push debit to another wallet ==> shows QR code to be scanned / link to be 
sent by mail or messenger
 public let VIEW_SEND_P2P = VIEW_DEPOSIT + 10                        // 50 Send 
Coins
-//public let VIEW_SEND_TOS                                          // 51 - 
user already accepted the ToS at withdrawal, invoice or receive
-public let VIEW_SEND_PURPOSE = VIEW_SEND_P2P + 2                    // 52
+//public let VIEW_SEND_TOS                                          // - user 
already accepted the ToS at withdrawal, invoice or receive
+public let VIEW_SEND_PURPOSE = VIEW_SEND_P2P + 2                    // 52 Send 
Purpose
 
 // MARK: P2P Private Receive (from Balances)
 // pull credit from another wallet ==> shows QR code to be scanned / link to 
be sent by mail or messenger
-public let VIEW_RECEIVE_P2P = VIEW_SEND_P2P + 10                    // 60 
Receive Amount
-public let VIEW_RECEIVE_TOS = VIEW_RECEIVE_P2P + 1                  // 61 
Receive ToS
-public let VIEW_RECEIVE_PURPOSE = VIEW_RECEIVE_TOS + 1              // 62 
Receive Purpose
+public let VIEW_REQUEST_P2P = VIEW_SEND_P2P + 10                    // 60 
Request Amount
+public let VIEW_REQUEST_TOS = VIEW_REQUEST_P2P + 1                  // 61 
Request ToS
+public let VIEW_REQUEST_PURPOSE = VIEW_REQUEST_TOS + 1              // 62 
Request Purpose
 
 // MARK: P2P Business Invoice (from Balances)
-// pull credit from another wallet ==> shows QR code to be scanned / link to 
be sent by mail or messenger
-public let VIEW_INVOICE_P2P = VIEW_RECEIVE_P2P + 10                 // 70 
Invoice Amount
-public let VIEW_INVOICE_TOS = VIEW_INVOICE_P2P + 1                  // 71 
Invoice ToS
-public let VIEW_INVOICE_PURPOSE = VIEW_INVOICE_TOS + 1              // 72 
Invoice Purpose
-
+// TBD
+//public let VIEW_INVOICE_P2P = VIEW_REQUEST_P2P + 10                 // 70 
Invoice Amount
+//public let VIEW_INVOICE_TOS = VIEW_INVOICE_P2P + 1                  // 71 
Invoice ToS
+//public let VIEW_INVOICE_PURPOSE = VIEW_INVOICE_TOS + 1              // 72 
Invoice Purpose
 
 
 // MARK: - Bank-Integrated Withdrawal
@@ -82,22 +81,22 @@ public let SHEET_WITHDRAW_CONFIRM = SHEET_WITHDRAW_ACCEPT + 
1       // 133 waiti
 public let SHEET_PAYMENT = SHEET_WITHDRAWAL + 10                    // 140 Pay 
Merchant
 public let SHEET_PAY_TEMPLATE = SHEET_PAYMENT + 2                   // 142 Pay 
Merchant Template
 
-// MARK: Reward - Receive Coins (from merchant)
-// openURL (Link, NFC or scan QR) ==> receive coins from merchant
-public let SHEET_RCV_REWARD = SHEET_PAYMENT + 10                    // 150 
Receive Reward
-
 // MARK: P2P Pay Invoice
 // p2p pull debit - openURL (Link or scan QR)
-public let SHEET_PAY_P2P = SHEET_RCV_REWARD + 10                    // 160 Pay 
P2P Invoice
-public let SHEET_PAY_P2P_ACCEPT = SHEET_PAY_P2P + 2                 // 162 Pay 
P2P AcceptView
+public let SHEET_PAY_P2P = SHEET_PAYMENT + 10                       // 150 Pay 
P2P Invoice
+public let SHEET_PAY_P2P_ACCEPT = SHEET_PAY_P2P + 2                 // 152 Pay 
P2P AcceptView
 
 // MARK: P2P Receive Coins
 // p2p push credit - openURL (Link or scan QR)
-public let SHEET_RCV_P2P = SHEET_PAY_P2P + 10                       // 170 
Receive P2P Coins
-public let SHEET_RCV_P2P_TOS = SHEET_RCV_P2P + 1                    // 171 
Receive P2P TOSView
-public let SHEET_RCV_P2P_ACCEPT = SHEET_RCV_P2P_TOS + 1             // 172 
Receive P2P AcceptView
+public let SHEET_RCV_P2P = SHEET_PAY_P2P + 10                       // 160 
Receive P2P Coins
+public let SHEET_RCV_P2P_TOS = SHEET_RCV_P2P + 1                    // 161 
Receive P2P TOSView
+public let SHEET_RCV_P2P_ACCEPT = SHEET_RCV_P2P_TOS + 1             // 162 
Receive P2P AcceptView
+
+// MARK: Reward - Receive Coins (from merchant)
+// openURL (Link, NFC or scan QR) ==> receive coins from merchant
+public let SHEET_RCV_REWARD = SHEET_RCV_P2P + 10                    // 170 
Receive Reward
 
-//public let SHEET_REFUND =
+public let SHEET_REFUND = SHEET_RCV_REWARD + 10                     // 180 
Receive Refunds
 
 extension UIDevice {
     var hasNotch: Bool {
@@ -128,6 +127,10 @@ struct DebugViewV: View {
                 .foregroundColor(.red)
                 .font(.system(size: 11))        // no accessibilityFont
                 .monospacedDigit()
+                .id("viewID")
+                .accessibilityLabel(Text("View.ID.", comment: 
"AccessibilityLabel"))
+                .accessibilityValue(viewIDString)
+                .accessibilityHint("Shows which view you currently are on.")
             Spacer()
         }
         .edgesIgnoringSafeArea(.top)
@@ -147,28 +150,31 @@ class DebugViewC: ObservableObject {
     @Published var viewID: Int = 0
     @Published var sheetID: Int = 0
 
+    func announce(this: String) {
+        if UIAccessibility.isVoiceOverRunning {
+            UIAccessibility.post(notification: .screenChanged, argument: this)
+        }
+    }
+
     @MainActor func setViewID(_ newID: Int, stack: CallStack) -> Void {
         if developerMode {
             if viewID == 0 {
-                symLog.log("switching ON, \(newID)")
-                logger.info("switching ON, \(newID, privacy: .public)")
+                logger.log("switching ON, \(newID, privacy: .public)")
                 viewID = newID                              // publish ON
+                announce(this: "Current view is: \(newID).")
             } else if viewID != newID {
-                symLog.log("switching from \(viewID) to \(newID)")
-                logger.info("switching from \(self.viewID, privacy: .public) 
to \(newID, privacy: .public)")
+                logger.log("switching from \(self.viewID, privacy: .public) to 
\(newID, privacy: .public)")
+                announce(this: "View switched from \(self.viewID) to 
\(newID).")
                 viewID = newID                              // publish new 
viewID
             } else {
-                symLog.log("\(newID) stays")
-                logger.info("\(newID, privacy: .public) stays")
+                logger.log("\(newID, privacy: .public) stays")
                 // don't set viewID to the same value, it would just trigger 
an unneccessary redraw
             }
         } else if viewID > 0 {
-            symLog.log("switching OFF, will not use \(newID)")
-            logger.info("switching OFF, will not use \(newID, privacy: 
.public)")
+            logger.log("switching OFF, will not use \(newID, privacy: 
.public)")
             viewID = 0                                      // publish OFF
         } else {
-            symLog.log("off, will not use \(newID)")
-            logger.info("off, will not use \(newID, privacy: .public)")
+            logger.log("off, will not use \(newID, privacy: .public)")
             // don't set viewID from 0 to 0 again, it would just trigger an 
unneccessary redraw
         }
     }
@@ -176,24 +182,19 @@ class DebugViewC: ObservableObject {
     @MainActor func setSheetID(_ newID: Int) -> Void {
         if developerMode {
             if sheetID != newID {
-                symLog.log("switching from \(sheetID) to \(newID)")
-                logger.info("switching from \(self.sheetID, privacy: .public) 
to \(newID, privacy: .public) for sheet")
+                logger.log("switching from \(self.sheetID, privacy: .public) 
to \(newID, privacy: .public) for sheet")
                 sheetID = newID                             // publish new 
sheetID
             } else {
-                symLog.log("\(newID) stays")
-                logger.info("\(newID, privacy: .public) stays for sheet")
+                logger.log("\(newID, privacy: .public) stays for sheet")
                 // don't set sheetID to the same value, it would just trigger 
an unneccessary redraw
             }
         } else if sheetID > 0 {
             // might happen after switching DevMode off, if sheetID still has 
the old value of the last sheet
-            symLog.log("switching OFF, will not use \(newID)")
-            logger.info("switching OFF, will not use \(newID, privacy: 
.public) for sheet")
+            logger.log("switching OFF, will not use \(newID, privacy: .public) 
for sheet")
             sheetID = 0                                     // publish OFF
         } else {
-            symLog.log("off, will not use \(newID)")
-            logger.info("off, will not use \(newID, privacy: .public) for 
sheet")
+            logger.log("off, will not use \(newID, privacy: .public) for 
sheet")
             // don't set sheetID from 0 to 0 again, it would just trigger an 
unneccessary redraw
         }
     }
-
 }
diff --git a/TalerWallet1/Controllers/PublicConstants.swift 
b/TalerWallet1/Controllers/PublicConstants.swift
index 3b778bd..ddcd126 100644
--- a/TalerWallet1/Controllers/PublicConstants.swift
+++ b/TalerWallet1/Controllers/PublicConstants.swift
@@ -13,6 +13,7 @@ public let ONEDAY: UInt = 1         // 1..3
 public let SEVENDAYS: UInt = 7      // 3..9
 public let THIRTYDAYS: UInt = 30    // 10..30
 
+public let EMPTYSTRING = ""                        // avoid automatic 
translation of empty "" textLiterals in Text()
 public let HTTPS = "https://";
 //public let DEMOBANK = HTTPS + "bAnK.dEmO.tAlEr.nEt"             // should be 
weird to read, but still work
 //public let DEMOEXCHANGE = HTTPS + "eXcHaNgE.dEmO.tAlEr.nEt"
diff --git a/TalerWallet1/Controllers/TalerWallet1App.swift 
b/TalerWallet1/Controllers/TalerWallet1App.swift
index 7f7fa50..9efb5be 100644
--- a/TalerWallet1/Controllers/TalerWallet1App.swift
+++ b/TalerWallet1/Controllers/TalerWallet1App.swift
@@ -10,8 +10,8 @@
  */
 import BackgroundTasks
 import SwiftUI
-import SymLog
 import os.log
+import SymLog
 
 @main
 struct TalerWallet1App: App {
@@ -37,7 +37,7 @@ struct TalerWallet1App: App {
 
     var body: some Scene {
         WindowGroup {
-            MainView(stack: CallStack("App"), soundPlayed: $soundPlayed)
+            MainView(logger: logger, stack: CallStack("App"), soundPlayed: 
$soundPlayed)
                 .environmentObject(debugViewC)      // change viewID / sheetID
                 .environmentObject(viewState)       // popToRoot
                 .environmentObject(controller)
diff --git a/TalerWallet1/Helper/LocalizedAlertError.swift 
b/TalerWallet1/Helper/LocalizedAlertError.swift
index 00070e5..513f93d 100644
--- a/TalerWallet1/Helper/LocalizedAlertError.swift
+++ b/TalerWallet1/Helper/LocalizedAlertError.swift
@@ -48,7 +48,7 @@ extension View {
                 error.wrappedValue = nil
             }
         } message: { error in
-            Text(error.failureReason ?? error.recoverySuggestion ?? "")
+            Text(error.failureReason ?? error.recoverySuggestion ?? 
EMPTYSTRING)
         }
     }
 }
diff --git a/TalerWallet1/Helper/TalerDater.swift 
b/TalerWallet1/Helper/TalerDater.swift
index 5bde4bc..427e0f9 100644
--- a/TalerWallet1/Helper/TalerDater.swift
+++ b/TalerWallet1/Helper/TalerDater.swift
@@ -65,7 +65,7 @@ public class TalerDater: DateFormatter {
         do {
             let milliseconds = try from.milliseconds()
             let date = Date(milliseconds: milliseconds)
-//            let date = date(from: from)
+
             if relative {
                 let now = Date.now
                 let timeInterval = now.timeIntervalSince(date)
@@ -75,8 +75,8 @@ public class TalerDater: DateFormatter {
             }
             return (shared.string(from: date), date)
         } catch {       // Never
-//            let never = LocalizedString("Never")
-            return ("Never", nil)
+            let never = String(localized: "No date", comment: "Timestamp 
missing or invalid")
+            return (never, nil)
         }
     }
 
diff --git a/TalerWallet1/Helper/WalletColors.swift 
b/TalerWallet1/Helper/WalletColors.swift
index 815da41..a358caf 100644
--- a/TalerWallet1/Helper/WalletColors.swift
+++ b/TalerWallet1/Helper/WalletColors.swift
@@ -45,7 +45,7 @@ public struct WalletColors {
         Color(.systemBackground)
     }
 
-    var uncompletedColor: Color {
+    var incompleteColor: Color {
         gray1
     }
     func pendingColor(_ incoming: Bool) -> Color {
diff --git a/TalerWallet1/Model/Model+Transactions.swift 
b/TalerWallet1/Model/Model+Transactions.swift
index 6c3869d..f8e171f 100644
--- a/TalerWallet1/Model/Model+Transactions.swift
+++ b/TalerWallet1/Model/Model+Transactions.swift
@@ -25,7 +25,7 @@ extension WalletModel {
             transaction.isPending
         }
     }
-    static func uncompletedTransactions(_ transactions: [Transaction]) -> 
[Transaction] {
+    static func incompleteTransactions(_ transactions: [Transaction]) -> 
[Transaction] {
         transactions.filter { transaction in
             !transaction.isDone && !transaction.isPending
         }
diff --git a/TalerWallet1/Model/Transaction.swift 
b/TalerWallet1/Model/Transaction.swift
index 823e1d7..ea1e599 100644
--- a/TalerWallet1/Model/Transaction.swift
+++ b/TalerWallet1/Model/Transaction.swift
@@ -73,17 +73,17 @@ enum TransactionMajorState: String, Codable {
     var localizedState: String {
         switch self {
             case .none:      return                   "none"
-            case .pending:   return String(localized: "Pending", comment: 
"TransactionMajorState")
-            case .done:      return String(localized: "Done", comment: 
"TransactionMajorState")
-            case .aborting:  return String(localized: "Aborting", comment: 
"TransactionMajorState")
-            case .aborted:   return String(localized: "Aborted", comment: 
"TransactionMajorState")
+            case .pending:   return String(localized: "MajorState.Pending", 
defaultValue: "Pending", comment: "TransactionMajorState")
+            case .done:      return String(localized: "MajorState.Done", 
defaultValue: "Done", comment: "TransactionMajorState")
+            case .aborting:  return String(localized: "MajorState.Aborting", 
defaultValue: "Aborting", comment: "TransactionMajorState")
+            case .aborted:   return String(localized: "MajorState.Aborted", 
defaultValue: "Aborted", comment: "TransactionMajorState")
             case .suspended: return                   "Suspended"
-            case .dialog:    return String(localized: "Dialog", comment: 
"TransactionMajorState")
+            case .dialog:    return String(localized: "MajorState.Dialog", 
defaultValue: "Dialog", comment: "TransactionMajorState")
             case .suspendedAborting: return           "AbortingSuspended"
-            case .failed:    return String(localized: "Failed", comment: 
"TransactionMajorState")
-            case .expired:   return String(localized: "Expired", comment: 
"TransactionMajorState")
-            case .deleted:   return String(localized: "Deleted", comment: 
"TransactionMajorState")
-            case .unknown:   return String(localized: "Unknown", comment: 
"TransactionMajorState")
+            case .failed:    return String(localized: "MajorState.Failed", 
defaultValue: "Failed", comment: "TransactionMajorState")
+            case .expired:   return String(localized: "MajorState.Expired", 
defaultValue: "Expired", comment: "TransactionMajorState")
+            case .deleted:   return String(localized: "MajorState.Deleted", 
defaultValue: "Deleted", comment: "TransactionMajorState")
+            case .unknown:   return String(localized: "MajorState.Unknown", 
defaultValue: "Unknown", comment: "TransactionMajorState")
         }
     }
 }
@@ -150,6 +150,7 @@ struct TransactionCommon: Decodable, Sendable {
     var transactionId: String
     var timestamp: Timestamp
     var txActions: [TxAction]
+    var kycUrl: String?
 
     func localizedType(_ type: TransactionType) -> String {
         switch type {
diff --git a/TalerWallet1/Model/WalletModel.swift 
b/TalerWallet1/Model/WalletModel.swift
index 1c6e884..588003b 100644
--- a/TalerWallet1/Model/WalletModel.swift
+++ b/TalerWallet1/Model/WalletModel.swift
@@ -46,7 +46,7 @@ class WalletModel: ObservableObject {
             return response
         } catch {       // rethrows
             let timeUsed = Date.now - sendTime
-            logger.error("\(request.operation(), privacy: .public) failed 
after \(timeUsed.milliseconds, privacy: .public) ms\n\(error)")
+            logger.error("\(request.operation(), privacy: .public) failed 
after \(timeUsed.milliseconds, privacy: .public) ms\n\(error, privacy: 
.public)")
             throw error
         }
     }
diff --git a/TalerWallet1/Views/Balances/BalanceRowView.swift 
b/TalerWallet1/Views/Balances/BalanceRowView.swift
index 4af0a15..2fb15ae 100644
--- a/TalerWallet1/Views/Balances/BalanceRowView.swift
+++ b/TalerWallet1/Views/Balances/BalanceRowView.swift
@@ -11,29 +11,34 @@ struct BalanceButton: View {
     let rowAction: () -> Void
 
     @AppStorage("iconOnly") var iconOnly: Bool = false
+    @Environment(\.colorSchemeContrast) private var colorSchemeContrast
+//    @AppStorage("moreContrast") var moreContrast: Bool = false
 
     var body: some View {
-        let balanceTitle = String(localized: "Balance:", comment: "Main view")
+        let balanceTitleStr = String(localized: "Balance:", comment: "Main 
view")
         Button(action: rowAction) {
             SingleAxisGeometryReader { width in         // e.g. 301 instead of 
313 => padding = 6
                 Group {
-                    let titles = [(balanceTitle, TalerFont.uiFont(.title2)),
+                    let title = iconOnly ? "" : balanceTitleStr
+                    let titles = [(balanceTitleStr, TalerFont.uiFont(.title2)),
                                   (amountStr,    TalerFont.uiFont(.title))]
                     let fitsSideBySide = iconOnly || 
Self.fitsSideBySide(titles, availableWidth: width,
                                                                   
sizeCategory: sizeCategory,
                                                                   padding: 20, 
sameSize: false)
                     AmountRowV(amountStr: amountStr, amountColor: .primary, 
largeAmountFont: true,
                                fitsHorizontal: fitsSideBySide, vertAlignment: 
.lastTextBaseline) {
-                        Text(iconOnly ? "" : balanceTitle)
+                        Text(title)
                             .accessibilityFont(.title2)
-                            .foregroundColor(.secondary)
+                            .foregroundColor(colorSchemeContrast == .increased 
? .primary : .secondary)
+//                            .foregroundColor(moreContrast ? .primary : 
.secondary)
                     }
                 }
             }
         }   .disabled(false)
             .buttonStyle(TalerButtonStyle(type: iconOnly ? .plain : .balance, 
aligned: .trailing))
-            .accessibilityElement(children: 
/*@START_MENU_TOKEN@*/.ignore/*@END_MENU_TOKEN@*/)
-            .accessibilityLabel("\(balanceTitle) \(amountStr)")    // TODO: 
CurrencyFormatter!
+            .accessibilityElement(children: .combine)
+            .accessibilityHint("Will go to main transactions list.")
+//            .accessibilityLabel(balanceTitleStr + " " + amountStr)    // 
TODO: CurrencyFormatter!
     }
 }
 
@@ -51,12 +56,18 @@ struct BalanceRowView: View {
     @AppStorage("iconOnly") var iconOnly: Bool = false
     @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
 
-    let sendTitle0 = String(localized: "Send", comment: "Abbreviation <Send 
Money>")
-    let sendTitle1 = String(localized: "Send", comment: "Top of button <Send 
Money>")
-    let sendTitle2 = String(localized: "Money", comment: "Bottom of button 
<Send Money>")
-    let requestTitle0 = String(localized: "Request", comment: "Abbreviation 
<Request Payment>")
-    let requestTitle1 = String(localized: "Request", comment: "Top of button 
<Request Payment>")
-    let requestTitle2 = String(localized: "Payment", comment: "Bottom of 
button <Request Payment>")
+    let sendTitle0 = String(localized: "SendButton_Short", defaultValue: 
"Send",
+                              comment: "Abbreviation of button `Send Money´")
+    let sendTitle1 = String(localized: "SendButton_Top", defaultValue: "Send",
+                              comment: "Top (first half) of button `Send 
Money´")
+    let sendTitle2 = String(localized: "SendButton_Bottom", defaultValue: 
"Money",
+                              comment: "Bottom (second half) of button `Send 
Money´")
+    let requestTitle0 = String(localized: "RequestButton_Short", defaultValue: 
"Request",
+                                 comment: "Abbreviation of button `Request 
Payment´")
+    let requestTitle1 = String(localized: "RequestButton_Top", defaultValue: 
"Request",
+                                 comment: "Top (first half) of button `Request 
Payment´")
+    let requestTitle2 = String(localized: "RequestButton_Bottom", 
defaultValue: "Payment",
+                                 comment: "Bottom (second half) of button 
`Request Payment´")
 
     var body: some View {
         SingleAxisGeometryReader { width in
diff --git a/TalerWallet1/Views/Balances/BalancesSectionView.swift 
b/TalerWallet1/Views/Balances/BalancesSectionView.swift
index a588698..d0a3718 100644
--- a/TalerWallet1/Views/Balances/BalancesSectionView.swift
+++ b/TalerWallet1/Views/Balances/BalancesSectionView.swift
@@ -22,6 +22,7 @@ struct BalancesSectionView {
     @Binding var centsToTransfer: UInt64
     @Binding var summary: String
 
+//    @AppStorage("moreContrast") var moreContrast: Bool = false
     @AppStorage("iconOnly") var iconOnly: Bool = false
     @EnvironmentObject private var model: WalletModel
     @EnvironmentObject private var controller: Controller
@@ -31,7 +32,7 @@ struct BalancesSectionView {
     @State private var transactions: [Transaction] = []
     @State private var completedTransactions: [Transaction] = []
     @State private var pendingTransactions: [Transaction] = []
-    @State private var uncompletedTransactions: [Transaction] = []
+    @State private var incompleteTransactions: [Transaction] = []
 
     func reloadOneAction(_ transactionId: String) async throws -> Transaction {
         return try await model.getTransactionByIdT(transactionId)
@@ -54,10 +55,10 @@ struct BalancesSectionView {
 //        sectionID = UUID()
     }
 
-    func reloadUncompleted(_ stack: CallStack) async -> () {
+    func reloadIncomplete(_ stack: CallStack) async -> () {
         let currency = balance.scopeInfo.currency
         transactions = await model.transactionsT(stack.push(), currency: 
currency)
-        uncompletedTransactions = 
WalletModel.uncompletedTransactions(transactions)
+        incompleteTransactions = 
WalletModel.incompleteTransactions(transactions)
 //        sectionID = UUID()
     }
 }
@@ -87,8 +88,7 @@ extension BalancesSectionView: View {
                         completedTransactions: $completedTransactions,
                               reloadAllAction: reloadCompleted,
                               reloadOneAction: reloadOneAction)
-            let hasPending = pendingTransactions.count > 0
-            if hasPending {
+            if pendingTransactions.count > 0 {
                 BalancesPendingRowView(symLog: symLog,
                                         stack: stack.push(),
                                  currencyInfo: currencyInfo,
@@ -96,21 +96,20 @@ extension BalancesSectionView: View {
                                 reloadPending: reloadPending,
                               reloadOneAction: reloadOneAction)
             }
-            let hasUncompleted = uncompletedTransactions.count > 0
-            if hasUncompleted {
+            if incompleteTransactions.count > 0 {
                 NavigationLink {
-//let _ = print("button: Uncompleted Transactions: \(currency)")
+//let _ = print("button: Incomplete Transactions: \(currency)")
                     LazyView {
                         TransactionsListView(stack: stack.push(),
-                                          navTitle: String(localized: 
"Uncompleted"),
+                                          navTitle: String(localized: 
"Incomplete", comment: "ViewTitle of TransactionList"),
                                       currencyInfo: currencyInfo,
-                                      transactions: uncompletedTransactions,
+                                      transactions: incompleteTransactions,
                                         showUpDown: false,
-                                   reloadAllAction: reloadUncompleted,
+                                   reloadAllAction: reloadIncomplete,
                                    reloadOneAction: reloadOneAction)
                     }
                 } label: {
-                    UncompletedRowView(uncompletedTransactions: 
$uncompletedTransactions)
+                    IncompleteRowV(incompleteTransactions: 
$incompleteTransactions)
                 }
 
             }
@@ -123,7 +122,7 @@ extension BalancesSectionView: View {
                 let response = await model.transactionsT(stack.push(".task - 
reload Transactions"), currency: currency)
                 transactions = response
                 pendingTransactions = WalletModel.pendingTransactions(response)
-                uncompletedTransactions = 
WalletModel.uncompletedTransactions(response)
+                incompleteTransactions = 
WalletModel.incompleteTransactions(response)
                 completedTransactions = 
WalletModel.completedTransactions(response)
                 shownSectionID = sectionID
 //            } else {
@@ -133,18 +132,8 @@ extension BalancesSectionView: View {
         let transactionCount = completedTransactions.count
         /// if there is only one currency, then show recent transactions
         if sectionCount == 1 && transactionCount > 0 {
-            let sortedTransactions = completedTransactions.sorted {
-                do {
-                    let first = try $0.common.timestamp.milliseconds()
-                    let second = try $1.common.timestamp.milliseconds()
-                    return first > second
-                } catch {
-                    symLog.log(error)
-                    return false        // should never happen
-                }
-            }
             Section {
-                let slice = sortedTransactions.prefix(3)
+                let slice = completedTransactions.prefix(3)         // already 
sorted
                 let threeTransactions = Array(slice)
                 TransactionsRowsView(symLog: symLog,
                                       stack: stack.push(),
@@ -155,6 +144,7 @@ extension BalancesSectionView: View {
                 if !iconOnly {
                     Text("Recent transactions")
                         .accessibilityFont(.callout)
+//                        .foregroundColor(moreContrast ? .primary : 
.secondary)
                 }
             }
         }
@@ -199,7 +189,7 @@ fileprivate struct BalancesPendingRowView: View {
             //let _ = print("button: Pending Transactions: \(currency)")
             LazyView {
                 TransactionsListView(stack: stack.push(),
-                                  navTitle: String(localized: "Pending"),
+                                  navTitle: String(localized: "Pending", 
comment: "ViewTitle of TransactionList"),
                               currencyInfo: currencyInfo,
                               transactions: pendingTransactions,
                                 showUpDown: false,
@@ -274,7 +264,7 @@ fileprivate struct BalancesNavigationLinksView: View {
 
             NavigationLink(destination: LazyView {
                 TransactionsListView(stack: stack.push(),
-                                  navTitle: String(localized: "Transactions"),
+                                  navTitle: String(localized: "Transactions", 
comment: "ViewTitle of TransactionList"),
                               currencyInfo: currencyInfo,
                               transactions: completedTransactions,
                                 showUpDown: true,
diff --git a/TalerWallet1/Views/Balances/IncompleteRowV.swift 
b/TalerWallet1/Views/Balances/IncompleteRowV.swift
new file mode 100644
index 0000000..f76e7fc
--- /dev/null
+++ b/TalerWallet1/Views/Balances/IncompleteRowV.swift
@@ -0,0 +1,39 @@
+/*
+ * This file is part of GNU Taler, ©2022-23 Taler Systems S.A.
+ * See LICENSE.md
+ */
+import SwiftUI
+import taler_swift
+
+/// This view shows an incompleteTransactions row in a currency section, below 
the balance
+struct IncompleteRowV: View {
+    @Binding var incompleteTransactions: [Transaction]
+
+    var body: some View {
+        let count = incompleteTransactions.count
+        HStack {
+            Spacer()
+            Text("\(count) incomplete transactions")
+                .accessibilityFont(.title2)
+                .foregroundColor(WalletColors().incompleteColor)
+            Spacer()
+        }
+    }
+}
+// MARK: - Preview
+#if DEBUG
+fileprivate struct IncompleteRowContainer: View {
+    @State var incompleteTransactions: [Transaction] = []
+
+    var body: some View {
+        IncompleteRowV(incompleteTransactions: $incompleteTransactions)
+    }
+}
+struct IncompleteRowV_Previews: PreviewProvider {
+    static var previews: some View {
+        List {
+            IncompleteRowContainer()
+        }
+    }
+}
+#endif
diff --git a/TalerWallet1/Views/Balances/PendingRowView.swift 
b/TalerWallet1/Views/Balances/PendingRowView.swift
index f45d1fa..c312006 100644
--- a/TalerWallet1/Views/Balances/PendingRowView.swift
+++ b/TalerWallet1/Views/Balances/PendingRowView.swift
@@ -27,8 +27,8 @@ struct PendingRowContentV: View {
             totalWidth = totalStr.widthOfString(usingUIFont: uiFont, 
sizeCategory)
         }
 
-    let logStr = String(format: "image: %.2f   title: %.2f   total: %.2f", 
imageWidth, max(title1Width, title2Width), totalWidth)
-    print(logStr)
+//    let logStr = String(format: "image: %.2f   title: %.2f   total: %.2f", 
imageWidth, max(title1Width, title2Width), totalWidth)
+//    print(logStr)
         return imageWidth + (isHorizontal ? totalWidth
                                           : max(title1Width, title2Width))
     }
@@ -59,12 +59,18 @@ struct PendingRowView: View {
     @Environment(\.sizeCategory) var sizeCategory
     @AppStorage("iconOnly") var iconOnly: Bool = false
 
-    let inTitle0 = String(localized: "Incoming", comment: "Abbreviation 
<pending incoming>")
-    let inTitle1 = String(localized: "Pending", comment: "Top of line <Pending 
incoming>")
-    let inTitle2 = String(localized: "incoming", comment: "Bottom of line 
<pending incoming>")
-    let outTitle0 = String(localized: "Outgoing", comment: "Abbreviation 
<pending outgoing>")
-    let outTitle1 = String(localized: "Pending", comment: "Top of line 
<Pending outgoing>")
-    let outTitle2 = String(localized: "outgoing", comment: "Bottom of line 
<pending outgoing>")
+    let inTitle0 = String(localized: "TitleIncoming_Short", defaultValue: 
"Incoming",
+                            comment: "Abbreviation of `Pending incoming´ in 
Balances")
+    let inTitle1 = String(localized: "TitleIncoming_Top", defaultValue: 
"Pending",
+                            comment: "Top (first half) of line `Pending 
incoming´ in Balances")
+    let inTitle2 = String(localized: "TitleIncoming_Bottom", defaultValue: 
"incoming",
+                            comment: "Bottom (second half) of line `Pending 
incoming´ in Balances")
+    let outTitle0 = String(localized: "TitleOutgoing_Short", defaultValue: 
"Outgoing",
+                             comment: "Abbreviation of `Pending outgoing´ in 
Balances")
+    let outTitle1 = String(localized: "TitleOutgoing_Top", defaultValue: 
"Pending",
+                             comment: "Top (first half) of line `Pending 
outgoing´ in Balances")
+    let outTitle2 = String(localized: "TitleOutgoing_Bottom", defaultValue: 
"outgoing",
+                             comment: "Bottom (second half) of line `Pending 
outgoing´ in Balances")
 
     func needVStack(available: CGFloat, contentWidth: CGFloat, valueWidth: 
CGFloat) -> Bool {
         if available > 20 {
diff --git a/TalerWallet1/Views/Balances/UncompletedRowView.swift 
b/TalerWallet1/Views/Balances/UncompletedRowView.swift
deleted file mode 100644
index a9436b6..0000000
--- a/TalerWallet1/Views/Balances/UncompletedRowView.swift
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * This file is part of GNU Taler, ©2022-23 Taler Systems S.A.
- * See LICENSE.md
- */
-import SwiftUI
-import taler_swift
-
-/// This view shows an uncompleted transaction row in a currency section
-struct UncompletedRowView: View {
-    @Binding var uncompletedTransactions: [Transaction]
-
-    var body: some View {
-        let count = uncompletedTransactions.count
-        HStack {
-            Spacer()
-            Text("\(count) uncompleted transactions")
-                .accessibilityFont(.title2)
-                .foregroundColor(WalletColors().uncompletedColor)
-            Spacer()
-        }
-        .accessibilityElement(children: .combine)
-    }
-}
-// MARK: -
-#if DEBUG
-//struct UncompletedRowView_Previews: PreviewProvider {
-//    static var previews: some View {
-//        let uncompletedTransactions: [Transaction] = []
-//        List {
-//            UncompletedRowView(uncompletedTransactions: 
uncompletedTransactions)
-//        }
-//    }
-//}
-#endif
diff --git a/TalerWallet1/Views/Exchange/ExchangeListView.swift 
b/TalerWallet1/Views/Exchange/ExchangeListView.swift
index 47c74c8..cc1d987 100644
--- a/TalerWallet1/Views/Exchange/ExchangeListView.swift
+++ b/TalerWallet1/Views/Exchange/ExchangeListView.swift
@@ -16,46 +16,83 @@ struct ExchangeListView: View {
 #else       // GNU Taler
     var hamburgerAction: () -> Void
 #endif
-
     @EnvironmentObject private var model: WalletModel
+    @State var showAlert: Bool = false
+    @State var newExchange: String = TESTEXCHANGE
 
-    @State private var exchanges: [Exchange] = []
-
-    // source of truth for the value the user enters in currencyField for 
exchange withdrawals
-    @State private var centsToTransfer: UInt64 = 0        // TODO: different 
values for different currencies?
-
-    func reloadExchanges() async -> Void {
-            exchanges = await model.listExchangesM()
-    }
-
-    func addExchange(_ exUrl: String) -> Void {
+    func addExchange(_ exchange: String) -> Void {
         Task { // runs on MainActor
-            symLog.log("adding: \(exUrl)")
+            symLog.log("adding: \(exchange)")
             do {
-                try await model.addExchange(url: exUrl)
-                symLog.log("added: \(exUrl)")
+                try await model.addExchange(url: exchange)
+                symLog.log("added: \(exchange)")
+                announce(this: "added: \(exchange)")
             } catch {    // TODO: error handling - couldn't add exchangeURL
                 symLog.log("error: \(error)")
             }
         }
     }
 
-    @State var showAlert: Bool = false
-    @State var newExchange: String = TESTEXCHANGE
-
     var body: some View {
-#if DEBUG
-        let _ = Self._printChanges()
-        let _ = symLog.vlog()       // just to get the # to compare it with 
.onAppear & onDisappear
-#endif
-        let plusAction: () -> Void = {
-//        withAnimation { showAlert = true }
-            showAlert = true
-        }
 #if TABBAR  // Taler Wallet
         let hamburger: HamburgerButton? = nil
 #else       // GNU Taler
-        let hamburger: HamburgerButton = HamburgerButton(action: 
hamburgerAction)
+        let hamburger = HamburgerButton(action: hamburgerAction)
+#endif
+        let accessibilityLabelStr = String(localized: "Add Exchange", comment: 
"accessibilityLabel for the + button")
+        let plusButton = PlusButton(accessibilityLabelStr: 
accessibilityLabelStr) {
+            showAlert = true
+        }
+        let addTitleStr = String(localized: "Add Exchange", comment: "title of 
the addExchange alert")
+        let addButtonStr = String(localized: "Add", comment: "button in the 
addExchange alert")
+        if #available(iOS 16.0, *) {
+            ExchangeListCommonV(symLog: symLog, stack: stack.push())
+                .navigationTitle(navTitle)
+                .navigationBarItems(leading: hamburger, trailing: plusButton)
+                .alert(addTitleStr, isPresented: $showAlert) {
+                    TextField("Exchange address", text: $newExchange)
+//                    .textFieldStyle(.roundedBorder)   Yikes: when adding 
style the alert will stop showing the textfield! Don't do this.
+                    Button(addButtonStr) {
+                        addExchange(newExchange)
+                    }
+                    Button("Cancel", role: .cancel) { }
+                } message: {
+                    Text("Please enter the exchange URL")
+                }
+        } else {    // iOS 15 cannot have a textfield in an alert, so we must
+            ExchangeListCommonV(symLog: symLog, stack: stack.push())
+                .navigationTitle(navTitle)
+                .navigationBarItems(leading: hamburger, trailing: plusButton)
+                .textFieldAlert(isPresented: $showAlert,
+                                      title: addTitleStr,
+                                   doneText: addButtonStr,
+                                       text: $newExchange) { text in
+                    addExchange(text)
+                }
+        }
+    }
+}
+
+struct ExchangeListCommonV: View {
+    let symLog: SymLogV?
+    let stack: CallStack
+//    @Binding var balances: [Balance]
+
+    @EnvironmentObject private var model: WalletModel
+
+    @State private var exchanges: [Exchange] = []
+
+    // source of truth for the value the user enters in currencyField for 
exchange withdrawals
+    @State private var centsToTransfer: UInt64 = 0        // TODO: different 
values for different currencies?
+
+    func reloadExchanges() async -> Void {
+        exchanges = await model.listExchangesM()
+    }
+
+    var body: some View {
+#if DEBUG
+        let _ = Self._printChanges()
+        let _ = symLog?.vlog()       // just to get the # to compare it with 
.onAppear & onDisappear
 #endif
         //Text("Exchanges...")
         Content(symLog: symLog,
@@ -64,10 +101,6 @@ struct ExchangeListView: View {
              exchanges: $exchanges,
        centsToTransfer: $centsToTransfer,
        reloadExchanges: reloadExchanges)
-        .navigationTitle(navTitle)
-        .navigationBarItems(leading: hamburger,
-                            trailing: PlusButton(action: plusAction)
-                                        .accessibilityLabel("Add Exchange"))
         .overlay {
             if exchanges.isEmpty {
                 Text("No Exchanges yet...")
@@ -75,24 +108,13 @@ struct ExchangeListView: View {
             }
         }
         .task {
-            symLog.log(".task")
+            symLog?.log(".task")
             await reloadExchanges()
         }
-        .textFieldAlert(isPresented: $showAlert, title: "Add Exchange",
-                        doneText: "Add", text: $newExchange, action: 
addExchange)
     }
 }
 // MARK: -
-//struct ExchangeAmount: Identifiable {
-//    let exchange: Exchange
-//    let amountAvailable: Amount
-//
-//    var id: String {    // needed for Identifiable
-//        exchange.exchangeBaseUrl
-//    }
-//}
-// MARK: -
-extension ExchangeListView {
+extension ExchangeListCommonV {
     struct Content: View {
         let symLog: SymLogV?
         let stack: CallStack
diff --git a/TalerWallet1/Views/Exchange/ExchangeRowView.swift 
b/TalerWallet1/Views/Exchange/ExchangeRowView.swift
index 7674c20..0ed21cb 100644
--- a/TalerWallet1/Views/Exchange/ExchangeRowView.swift
+++ b/TalerWallet1/Views/Exchange/ExchangeRowView.swift
@@ -18,7 +18,8 @@ struct ExchangeRowView: View {
 
     func selectAndUpdate(_ button: Int) {
         buttonSelected = button      // will trigger NavigationLink
-        // TODO: while navigation animation runs, contact Exchange to update 
Fees
+        // TODO: after user tapped a button, while navigation animation runs, 
contact Exchange to update Fees
+        // cannot be uncommented yet since there is no scopeInfo
 //        Task { // runs on MainActor
 //            do {
 //                try await model.updateExchange(scopeInfo: balance.scopeInfo)
@@ -28,8 +29,6 @@ struct ExchangeRowView: View {
 //        }
     }
 
-
-//    func
     func titles(_ title: String) -> (String, String?) {
         if let separatorIndex = title.firstIndex(of: "\n") {
             let title1 = String(title[..<separatorIndex])
@@ -48,12 +47,15 @@ struct ExchangeRowView: View {
     }
 
     var body: some View {
-        let depositTitle0 = String(localized: "Deposit", comment: 
"Abbreviation <Deposit (currency)>")
-        let depositTitle1 = String(localized: "Deposit\n\(currency)",
-                                   comment: "Button <Deposit (currency)>, must 
have ONE \n and ONE %s")
-        let withdrawTitle0 = String(localized: "Withdraw", comment: 
"Abbreviation <Withdraw (currency)>")
-        let withdrawTitle1 = String(localized: "Withdraw\n\(currency)",
-                                    comment: "Button <Withdraw (currency)>, 
must have ONE \n and ONE %s")
+        let depositTitle0 = String(localized: "DepositButton_Short", 
defaultValue: "Deposit",
+                                   comment: "Abbreviation of `Deposit 
(currency)´")
+                    // TODO: deal with \t
+        let depositTitle1 = String(localized: "Deposit\t\(currency)",
+                                   comment: "Button `Deposit (currency)´, must 
have ONE \\t and ONE %@")
+        let withdrawTitle0 = String(localized: "WithdrawButton_Short", 
defaultValue: "Withdraw",
+                                    comment: "Abbreviation of `Withdraw 
(currency)´")
+        let withdrawTitle1 = String(localized: "Withdraw\t\(currency)",
+                                    comment: "Button `Withdraw (currency)´, 
must have ONE \\t and ONE %@")
         let baseURL = exchange.exchangeBaseUrl
 
         HStack(spacing: 0) {    // can't use the built in Label because it 
adds the accessory arrow
diff --git a/TalerWallet1/Views/Exchange/ExchangeSectionView.swift 
b/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
index e13ebc1..6e2afab 100644
--- a/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
+++ b/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
@@ -28,7 +28,6 @@ struct ExchangeSectionView: View {
                              currency: currency,            // TODO: 
(balance.available) amount.isZero to disable Deposit-button
                       centsToTransfer: $centsToTransfer)
             }
-            .accessibilityElement(children: .combine)
         } header: {
             BarGraphHeader(stack: stack.push(), currency: currency)
         }
diff --git a/TalerWallet1/Views/Exchange/ManualWithdraw.swift 
b/TalerWallet1/Views/Exchange/ManualWithdraw.swift
index 0492c95..dc98268 100644
--- a/TalerWallet1/Views/Exchange/ManualWithdraw.swift
+++ b/TalerWallet1/Views/Exchange/ManualWithdraw.swift
@@ -27,7 +27,7 @@ struct ManualWithdraw: View {
         let _ = symLog.vlog()       // just to get the # to compare it with 
.onAppear & onDisappear
 #endif
         let currency = exchange.currency ?? String(localized: "Unknown", 
comment: "unknown currency")
-        let navTitle = String(localized: "Withdraw \(currency)")
+        let navTitle = String(localized: "NavTitle_Withdraw (currency)", 
defaultValue: "Withdraw \(currency)")
         let currencyField = CurrencyField(value: $centsToTransfer, currency: 
currency) // becomeFirstResponder
 //        let agePicker = AgePicker(ageMenuList: $ageMenuList, selectedAge: 
$selectedAge)
 
diff --git a/TalerWallet1/Views/Exchange/QuiteSomeCoins.swift 
b/TalerWallet1/Views/Exchange/QuiteSomeCoins.swift
index 961d9d6..f1e5589 100644
--- a/TalerWallet1/Views/Exchange/QuiteSomeCoins.swift
+++ b/TalerWallet1/Views/Exchange/QuiteSomeCoins.swift
@@ -57,8 +57,8 @@ struct QuiteSomeCoins: View {
         if !someCoins.invalid {
             if !someCoins.tooMany {
                 if someCoins.manyCoins {
-                    Text(someCoins.quiteSome ? "Warning: It will take quite 
some time to withdraw this amount!"
-                                             : "Warning: It will take some 
time to withdraw this amount.")
+                    Text(someCoins.quiteSome ? "Note: It will take quite some 
time to withdraw this amount! Be more patient..."
+                                             : "Note: It will take some time 
to withdraw this amount. Be patient...")
                     .foregroundColor(someCoins.quiteSome ? .red : .primary)
                     .accessibilityFont(.body)
                     .multilineTextAlignment(.leading)
diff --git a/TalerWallet1/Views/HelperViews/AmountRowV.swift 
b/TalerWallet1/Views/HelperViews/AmountRowV.swift
index b3140e7..ac741f9 100644
--- a/TalerWallet1/Views/HelperViews/AmountRowV.swift
+++ b/TalerWallet1/Views/HelperViews/AmountRowV.swift
@@ -49,6 +49,8 @@ struct AmountRowV<Content: View>: View {
 
 struct SectionWithAmountRow: View {
     @Environment(\.sizeCategory) var sizeCategory
+    @Environment(\.colorSchemeContrast) private var colorSchemeContrast
+
     var body: some View {
         let testInfo = PreviewCurrencyInfo(TESTCURRENCY, digits: 0)
         let demoInfo = PreviewCurrencyInfo(DEMOCURRENCY, digits: 2)
@@ -60,24 +62,28 @@ struct SectionWithAmountRow: View {
             Section {
                 AmountRowV(amountStr: demoStr, amountColor: .primary, 
largeAmountFont: true,
                            fitsHorizontal: true, vertAlignment: 
.lastTextBaseline) {
-                    Text("Balance")
+                    Text(verbatim: "Balance")
+                        .foregroundColor(colorSchemeContrast == .increased ? 
.primary : .secondary)
                         .accessibilityFont(.title2)
                 }
                 AmountRowV(amountStr: demoStr, amountColor: .primary, 
largeAmountFont: true,
                            fitsHorizontal: false, vertAlignment: 
.lastTextBaseline) {
-                    Text("Balance")
+                    Text(verbatim: "Balance")
+                        .foregroundColor(colorSchemeContrast == .increased ? 
.primary : .secondary)
                         .accessibilityFont(.title2)
                 }
             }
             Section {
-                AmountRowV(amountStr: testStr, amountColor: .secondary, 
largeAmountFont: false,
+                AmountRowV(amountStr: testStr, amountColor: .primary, 
largeAmountFont: false,
                            fitsHorizontal: true, vertAlignment: 
.lastTextBaseline) {
-                    Text("Balance")
+                    Text(verbatim: "Balance")
+                        .foregroundColor(colorSchemeContrast == .increased ? 
.primary : .secondary)
                         .accessibilityFont(.title2)
                 }
                 AmountRowV(amountStr: testStr, amountColor: .secondary, 
largeAmountFont: false,
                            fitsHorizontal: false, vertAlignment: 
.lastTextBaseline) {
-                    Text("Balance")
+                    Text(verbatim: "Balance")
+                        .foregroundColor(colorSchemeContrast == .increased ? 
.primary : .secondary)
                         .accessibilityFont(.title2)
                 }
             }
diff --git a/TalerWallet1/Views/HelperViews/BarGraph.swift 
b/TalerWallet1/Views/HelperViews/BarGraph.swift
index dd66634..9eb61dc 100644
--- a/TalerWallet1/Views/HelperViews/BarGraph.swift
+++ b/TalerWallet1/Views/HelperViews/BarGraph.swift
@@ -12,6 +12,7 @@ struct BarGraphHeader: View {
     let stack: CallStack
     let currency: String
 
+//    @AppStorage("moreContrast") var moreContrast: Bool = false
     @EnvironmentObject private var model: WalletModel
     @State private var completedTransactions: [Transaction] = []
 
@@ -19,6 +20,7 @@ struct BarGraphHeader: View {
         HStack (alignment: .center, spacing: 10) {
             Text(currency)
                 .accessibilityFont(.title2)
+//                .foregroundColor(moreContrast ? .primary : .secondary)
             BarGraph(transactions: $completedTransactions,
                      maxBars: MAXBARS, barHeight: 10)       // TODO: barHeight 
relative to fontSize
         }
diff --git a/TalerWallet1/Views/HelperViews/Buttons.swift 
b/TalerWallet1/Views/HelperViews/Buttons.swift
index 945c86e..f221ac6 100644
--- a/TalerWallet1/Views/HelperViews/Buttons.swift
+++ b/TalerWallet1/Views/HelperViews/Buttons.swift
@@ -41,6 +41,7 @@ struct QRButton : View  {
 }
 
 struct PlusButton : View  {
+    let accessibilityLabelStr: String
     let action: () -> Void
 
     var body: some View {
@@ -48,7 +49,7 @@ struct PlusButton : View  {
             Image(systemName: "plus")
         }
         .accessibilityFont(.title)
-        .accessibilityLabel("Add...")
+        .accessibilityLabel(accessibilityLabelStr)
     }
 }
 
@@ -189,170 +190,12 @@ struct TalerButtonStyle: ButtonStyle {
     }
 }
 
-
-struct Buttons_Previews: PreviewProvider {
+#if DEBUG
+fileprivate struct ContentView_Previews: PreviewProvider {
     static var previews: some View {
-        VStack {
-            HStack {
-                Button("1000") {
-                    Controller.shared.playSound(1000)
-                }.padding()
-                Button("1013") {
-                    Controller.shared.playSound(1013)
-                }.padding()
-                Button("1008") {
-                    Controller.shared.playSound(1008)
-                }.padding()
-                Button("1001") {
-                    Controller.shared.playSound(1001)
-                }.padding()
-                Button("1018") {
-                    Controller.shared.playSound(1018)
-                }.padding()
-            } // Single
-            HStack {
-                Button("1003") {
-                    Controller.shared.playSound(1003)
-                }.padding()
-                Button("1004") {
-                    Controller.shared.playSound(1004)
-                }.padding()
-                Button("1016") {
-                    Controller.shared.playSound(1016)
-                }.padding()
-                Button("1022") {
-                    Controller.shared.playSound(1022)
-                }.padding()
-                Button("1034") {
-                    Controller.shared.playSound(1034)
-                }.padding()
-            } // Double
-            HStack {
-                Button("1023") {
-                    Controller.shared.playSound(1023)
-                }.padding()
-                Button("1029") {
-                    Controller.shared.playSound(1029)
-                }.padding()
-                Button("1014") {
-                    Controller.shared.playSound(1014)
-                }.padding()
-                Button("1021") {
-                    Controller.shared.playSound(1021)
-                }.padding()
-                Button("1031") {
-                    Controller.shared.playSound(1031)
-                }.padding()
-            } // long single
-            HStack {
-                Button("1002") {
-                    Controller.shared.playSound(1002) // == 7,12,15
-                }.padding()
-                Button("1006") {
-                    Controller.shared.playSound(1006)
-                }.padding()
-                Button("1025") {
-                    Controller.shared.playSound(1025)
-                }.padding()
-                Button("1026") {
-                    Controller.shared.playSound(1026)
-                }.padding()
-                Button("1033") {
-                    Controller.shared.playSound(1033)
-                }.padding()
-            } // Triple
-            HStack {
-                Button("1005") {
-                    Controller.shared.playSound(1005) // 17
-                }.padding()
-                Button("1009") {
-                    Controller.shared.playSound(1009)
-                }.padding()
-                Button("1010") {
-                    Controller.shared.playSound(1010)
-                }.padding()
-            } // Double 2
-            HStack {
-                Button("1030") {
-                    Controller.shared.playSound(1030)
-                }.padding()
-                Button("1035") {
-                    Controller.shared.playSound(1035)
-                }.padding()
-                Button("1036") {
-                    Controller.shared.playSound(1036)
-                }.padding()
-                Button("1027") {
-                    Controller.shared.playSound(1027)
-                }.padding()
-            }
-            HStack {
-                Button("1020") {
-                    Controller.shared.playSound(1020)
-                }.padding()
-                Button("1024") {
-                    Controller.shared.playSound(1024)
-                }.padding()
-                Button("1032") {
-                    Controller.shared.playSound(1032)
-                }.padding()
-                Button("1028") {
-                    Controller.shared.playSound(1028)
-                }.padding()
-            }
-            HStack {
-                PlusButton() {
-                }.padding()
-                HamburgerButton() {
-                }.padding()
-                QRButton() {
-                }.padding()
-                ReloadButton(disabled: false) {
-                }.padding()
-                ReloadButton(disabled: true) {
-                }.padding()
-            }
-            Button(String(localized: "Accept"), action: {
-                Controller.shared.playSound(1028)
-            })
-                .buttonStyle(TalerButtonStyle(type: .prominent))
-                .padding(.horizontal)
-        }
+        let testButtonTitle = String("Placeholder")
+        Button(testButtonTitle) {}
+            .buttonStyle(TalerButtonStyle(type: .balance, aligned: .trailing))
     }
 }
-
-#if DEBUG
-//fileprivate struct ContentView: View {
-//    @State var isOn = false
-//    //The better route is to have a separate variable to control the 
animations
-//    // This prevents unpleasant side-effects.
-//    @State private var animate = false
-//
-//    var body: some View {
-//        VStack {
-//            Text(verbatim: "I don't change.")
-//                .padding()
-//            Button("Press me, I do change") {
-//                isOn.toggle()
-//                animate = false
-//                // Because .opacity is animated, we need to switch it
-//                // back so the button shows.
-//                DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
-//                    animate = true
-//                }
-//            }
-//            // In this case I chose to animate .opacity
-//            .opacity(animate ? 1 : 0)
-//            .animation(.easeIn, value: animate)
-//            .frame(width: 300, height: 400)
-//            // If you want the button to animate when the view appears, you 
need to change the value
-//            .onAppear { animate = true }
-//        }
-//    }
-//}
-//fileprivate struct ContentView_Previews: PreviewProvider {
-//    static var previews: some View {
-//        ContentView()
-//    }
-//}
 #endif
diff --git a/TalerWallet1/Views/HelperViews/CopyShare.swift 
b/TalerWallet1/Views/HelperViews/CopyShare.swift
index c3825fd..500759b 100644
--- a/TalerWallet1/Views/HelperViews/CopyShare.swift
+++ b/TalerWallet1/Views/HelperViews/CopyShare.swift
@@ -22,13 +22,17 @@ struct CopyButton: View {
         Button(action: copyAction) {
             if vertical {
                 VStack {
+                    let shortCopy = String(localized: "Copy.short", 
defaultValue: "Copy", comment: "5 letters max, else abbreviate")
                     Image(systemName: "doc.on.doc")
-                    Text("Copy", comment: "5 letters max, else abbreviate")
+                        .accessibility(hidden: true)
+                    Text(shortCopy)
                 }
             } else {
+                let longCopy = String(localized: "Copy.long", defaultValue: 
"Copy", comment: "may be a bit longer")
                 HStack {
                     Image(systemName: "doc.on.doc")
-                    Text("Copy", comment: "may be a bit longer")
+                        .accessibility(hidden: true)
+                    Text(longCopy)
                 }
             }
         }
@@ -53,6 +57,7 @@ struct ShareButton: View {
         Button(action: shareAction) {
             HStack {
                 Image(systemName: "square.and.arrow.up")
+                    .accessibility(hidden: true)
                 Text("Share")
             }
         }
diff --git a/TalerWallet1/Views/HelperViews/LaunchAnimationView.swift 
b/TalerWallet1/Views/HelperViews/LaunchAnimationView.swift
index de4712d..8e923ca 100644
--- a/TalerWallet1/Views/HelperViews/LaunchAnimationView.swift
+++ b/TalerWallet1/Views/HelperViews/LaunchAnimationView.swift
@@ -18,18 +18,23 @@ struct RotatingTaler: View {
     let size: CGFloat
     @Binding var rotationEnabled: Bool
     @State private var rotationDirection = false
+#if TABBAR  // Taler Wallet
+    let logo = "taler-logo-2023-blue"
+#else       // GNU Taler
+    let logo = "taler-logo-2023-red"
+#endif
 
     private let animationTimer = Timer
         .publish(every: 1.6, on: .current, in: .common)
         .autoconnect()
 
     var body: some View {
-        Image("taler-logo-2023-red")
+        Image(logo)
             .resizable()
             .scaledToFit()
             .frame(width: size, height: size)
             .rotationEffect(rotationDirection ? Angle(degrees: 0) : 
Angle(degrees: 900))
-            .accessibilityHidden(true)          // decorative logo
+            .accessibilityLabel("Taler Logo")       // decorative logo - with 
button function
             .onReceive(animationTimer) { timerValue in
                 if rotationEnabled {
                     withAnimation(.easeInOut(duration: 1.9)) {
diff --git a/TalerWallet1/Views/HelperViews/QRCodeDetailView.swift 
b/TalerWallet1/Views/HelperViews/QRCodeDetailView.swift
index 3f7b139..2af6d8a 100644
--- a/TalerWallet1/Views/HelperViews/QRCodeDetailView.swift
+++ b/TalerWallet1/Views/HelperViews/QRCodeDetailView.swift
@@ -15,7 +15,7 @@ struct QRCodeDetailView: View {
     var body: some View {
         if talerURI.count > 10 {
             Section {
-                Text("Either")
+                Text("Either", comment: "Either (copy/share)")
                     .multilineTextAlignment(.leading)
                     .accessibilityFont(.title3)
 //                    .padding(.vertical)
@@ -26,9 +26,9 @@ struct QRCodeDetailView: View {
 //                    .padding(.bottom)
                     .listRowSeparator(.hidden)
 
-                let otherParty = incoming ? String(localized: "payer")
-                                          : String(localized: "payee")
-                Text("the link to the \(otherParty), or", comment: 
"(copy/share) the link to the other party (payer/payee), or")
+                let otherParty = incoming ? String(localized: "payer", 
comment: "the payment link to the (otherParty), or")
+                                          : String(localized: "payee", 
comment: "the payment link to the (otherParty), or")
+                Text("the payment link to the \(otherParty), or", comment:  
"...the payment link to the (payer/payee), or")
                     .multilineTextAlignment(.leading)
                     .accessibilityFont(.title3)
                     .listRowSeparator(.hidden)
diff --git a/TalerWallet1/Views/HelperViews/SelectDays.swift 
b/TalerWallet1/Views/HelperViews/SelectDays.swift
index 95a7182..081f924 100644
--- a/TalerWallet1/Views/HelperViews/SelectDays.swift
+++ b/TalerWallet1/Views/HelperViews/SelectDays.swift
@@ -34,40 +34,54 @@ struct SelectDays: View {
     }
 
     var body: some View {
-        HStack {
-            Button(action: oneDayAction) {
-                if developerMode {
-                    Text(verbatim: "3 Min.")
-                } else {
-                    Text("\(ONEDAY) Day", comment: "1 Day, might get plural 
(e.g. 2..3 Days), 4 letters max., abbreviate if longer")     // TODO: Plural
-                }
-            }.buttonStyle(TalerButtonStyle(type: (selected == ONEDAY) ? 
.prominent : .bordered, dimmed: true))
-                .disabled(!isEnabled)
+        let selectedStr = String(localized: "selected", comment: "VoiceOver 
hint which button is selected")
 
-            Button(action: sevenDayAction) {
-                if developerMode {
-                    Text(verbatim: "1 Hour")
-                } else {
-                    Text("\(SEVENDAYS) Days", comment: "7 Days, always plural 
(3..9), 4 letters max., abbreviate if longer")
-                }
-            }.buttonStyle(TalerButtonStyle(type: (selected == SEVENDAYS) ? 
.prominent : .bordered, dimmed: true))
-                .disabled(!isEnabled || maxExpiration < SEVENDAYS)
+        Section {   // (alignment: .leading)
+            Text("Expires in:")
+                .accessibilityLabel("Choose the expiration duration")
+                .accessibilityAddTraits(.isHeader)
+                .accessibilityRemoveTraits(.isStaticText)
+                .accessibilityFont(.title3)
+            HStack {
+                Button(action: oneDayAction) {
+                    if developerMode {
+                        Text(verbatim: "3 Min.")
+                    } else {
+                        Text("\(ONEDAY) Day", comment: "1 Day, might get 
plural (e.g. 2..3 Days), 4 letters max., abbreviate if longer")     // TODO: 
Plural
+                    }
+                }.buttonStyle(TalerButtonStyle(type: (selected == ONEDAY) ? 
.prominent : .bordered, dimmed: true))
+                    .accessibilityValue((selected == ONEDAY) ? selectedStr : 
EMPTYSTRING)
+                    .disabled(!isEnabled)
 
-            Button(action: thirtyDayAction) {
-                if developerMode {
-                    Text(verbatim: "1 Day")
-                } else {
-                    Text("\(THIRTYDAYS) Days", comment: "30 Days, always 
plural (10..30), 4 letters max., abbreviate if longer")
-                }
-            }.buttonStyle(TalerButtonStyle(type: (selected == THIRTYDAYS) ? 
.prominent : .bordered, dimmed: true))
-                .disabled(!isEnabled || maxExpiration < THIRTYDAYS)
-        } // 3 buttons
+                Button(action: sevenDayAction) {
+                    if developerMode {
+                        Text(verbatim: "1 Hour")
+                    } else {
+                        Text("\(SEVENDAYS) Days", comment: "7 Days, always 
plural (3..9), 4 letters max., abbreviate if longer")
+                    }
+                }.buttonStyle(TalerButtonStyle(type: (selected == SEVENDAYS) ? 
.prominent : .bordered, dimmed: true))
+                    .accessibilityValue((selected == SEVENDAYS) ? selectedStr 
: EMPTYSTRING)
+                    .disabled(!isEnabled || maxExpiration < SEVENDAYS)
+
+                Button(action: thirtyDayAction) {
+                    if developerMode {
+                        Text(verbatim: "1 Day")
+                    } else {
+                        Text("\(THIRTYDAYS) Days", comment: "30 Days, always 
plural (10..30), 4 letters max., abbreviate if longer")
+                    }
+                }.buttonStyle(TalerButtonStyle(type: (selected == THIRTYDAYS) 
? .prominent : .bordered, dimmed: true))
+                    .accessibilityValue((selected == THIRTYDAYS) ? selectedStr 
: EMPTYSTRING)
+                    .disabled(!isEnabled || maxExpiration < THIRTYDAYS)
+            } // 3 buttons
+        }
     }
 }
-
-//struct SelectDays_Previews: PreviewProvider {
-//    static var previews: some View {
-//        @State var expireDays: UInt = 1
-//        SelectDays(selected: $expireDays, maxExpiration: 20)
-//    }
-//}
+// MARK: -
+#if DEBUG
+struct SelectDays_Previews: PreviewProvider {
+    static var previews: some View {
+        @State var expireDays: UInt = 1
+        SelectDays(selected: $expireDays, maxExpiration: 20)
+    }
+}
+#endif
diff --git a/TalerWallet1/Views/HelperViews/TextFieldAlert.swift 
b/TalerWallet1/Views/HelperViews/TextFieldAlert.swift
index f665620..c29bba3 100644
--- a/TalerWallet1/Views/HelperViews/TextFieldAlert.swift
+++ b/TalerWallet1/Views/HelperViews/TextFieldAlert.swift
@@ -15,10 +15,13 @@ struct TextFieldAlert: ViewModifier {
         ZStack(alignment: .center) {
             content
                 .disabled(isPresented)
+                .accessibilityElement(children: isPresented ? .ignore : 
.contain)
             if isPresented {
                 VStack {
                     Text(title)
                         .accessibilityFont(.headline)
+                        .accessibilityAddTraits(.isHeader)
+                        .accessibilityRemoveTraits(.isStaticText)
                         .padding()
                     TextField(placeholder, text: 
$text).textFieldStyle(.roundedBorder).padding()
                     Divider()
@@ -40,6 +43,7 @@ struct TextFieldAlert: ViewModifier {
                         Spacer()
                     }
                 }
+                    .accessibility(addTraits: .isModal)
                     .background(.background)
                     .frame(width: 300, height: 200)
                     .cornerRadius(20)
diff --git a/TalerWallet1/Views/HelperViews/View+fitsSideBySide.swift 
b/TalerWallet1/Views/HelperViews/View+fitsSideBySide.swift
index a76011c..fa4ca83 100644
--- a/TalerWallet1/Views/HelperViews/View+fitsSideBySide.swift
+++ b/TalerWallet1/Views/HelperViews/View+fitsSideBySide.swift
@@ -5,6 +5,15 @@
 import SwiftUI
 import UIKit
 
+extension View {
+    @MainActor
+    public func announce(this: String) {
+        if UIAccessibility.isVoiceOverRunning {
+            UIAccessibility.post(notification: .screenChanged, argument: this)
+        }
+    }
+}
+
 extension View {
     /// if sameSize then this searches for the longest title
     /// returns true if any of the strings in 'titles' wouldn't fit in a view 
1/'numViews' of the size of 'width', with 'spacing'
diff --git a/TalerWallet1/Views/Main/MainView.swift 
b/TalerWallet1/Views/Main/MainView.swift
index 301ad27..128f214 100644
--- a/TalerWallet1/Views/Main/MainView.swift
+++ b/TalerWallet1/Views/Main/MainView.swift
@@ -3,6 +3,7 @@
  * See LICENSE.md
  */
 import SwiftUI
+import os.log
 import SymLog
 
 // Use this to delay instantiation when using `NavigationLink`, etc...
@@ -15,6 +16,7 @@ struct LazyView<Content: View>: View {
 
 struct MainView: View {
     private let symLog = SymLogV(0)
+    let logger: Logger
     let stack: CallStack
     @EnvironmentObject private var viewState: ViewState         // 
popToRootView()
     @EnvironmentObject private var controller: Controller
@@ -33,7 +35,7 @@ struct MainView: View {
 #endif
         Group {
             if controller.backendState == .ready {
-                Content(symLog: symLog, stack: stack.push("Content"), 
talerFont: $talerFont)
+                Content(symLog: symLog, logger: logger, stack: 
stack.push("Content"), talerFont: $talerFont)
                 // any change to rootViewId triggers popToRootView behaviour
                     .id(viewState.rootViewId)
                     .onAppear() {
@@ -74,6 +76,7 @@ enum Tab {
 extension MainView {
     struct Content: View {
         let symLog: SymLogV?
+        let logger: Logger
         let stack: CallStack
         @State private var shouldReloadBalances = 0
         @State private var balances: [Balance] = []
@@ -81,11 +84,24 @@ extension MainView {
         @AppStorage("iconOnly") var iconOnly: Bool = false
         @EnvironmentObject private var controller: Controller
         @EnvironmentObject private var model: WalletModel
-        let balancesTitle = String(localized: "Balances")
-        let exchangesTitle = String(localized: "Exchanges")
-        let settingsTitle = String(localized: "Settings")
+        let balancesTitle = String(localized: "TitleBalances", defaultValue: 
"Balances")
+        let exchangesTitle = String(localized: "TitleExchanges", defaultValue: 
"Exchanges")
+        let settingsTitle = String(localized: "TitleSettings", defaultValue: 
"Settings")
 #if TABBAR  // Taler Wallet
         @State private var selectedTab: Tab = .balances
+        @State private var showKycAlert: Bool = false
+
+        private var openKycButton: some View {
+            Button("KYC") {
+                showKycAlert = false
+//                UIApplication.shared.open(URL(string: 
UIApplication.openSettingsURLString)!)
+            }
+        }
+        private var dismissAlertButton: some View {
+            Button("Cancel", role: .cancel) {
+                showKycAlert = false
+            }
+        }
 
         private func tabSelection() -> Binding<Tab> {
             Binding { //this is the get block
@@ -142,12 +158,12 @@ extension MainView {
             // "@self" marks that the view value itself has changed, and 
"@identity" marks that the
             // identity of the view has changed (that is, that the persistent 
data associated with
             // the view has been recycled for a new instance of the same type)
-            if #available(iOS 17.1, *) {
-                // logs at INFO level, “com.apple.SwiftUI” subsystem, category 
“Changed Body Properties”
-                let _ = Self._logChanges()
-            } else {
+//            if #available(iOS 17.1, *) {
+//                // logs at INFO level, “com.apple.SwiftUI” subsystem, 
category “Changed Body Properties”
+//                let _ = Self._logChanges()
+//            } else {
                 let _ = Self._printChanges()
-            }
+//            }
             let _ = symLog?.vlog()       // just to get the identity # to 
compare with .onAppear & .onDisappear
 #endif
           Group {
@@ -162,6 +178,7 @@ extension MainView {
                 }.navigationViewStyle(.stack)
                 .tabItem {
                     Image(systemName: "chart.bar.xaxis")             // 
creditcard     system will automatically use filled variant
+                        .accessibilityLabel(balancesTitle)
                     if !iconOnly { Text(balancesTitle) }
                 }
                 .tag(Tab.balances)
@@ -174,6 +191,7 @@ extension MainView {
                 }.navigationViewStyle(.stack)
                 .tabItem {
                     Image(systemName: "building.columns")
+                        .accessibilityLabel(exchangesTitle)
                     if !iconOnly { Text(exchangesTitle) }
                 }
                 .tag(Tab.exchanges)
@@ -183,6 +201,7 @@ extension MainView {
                 }.navigationViewStyle(.stack)
                 .tabItem {
                     Image(systemName: "gear")                   // system will 
automatically use filled variant
+                        .accessibilityLabel(settingsTitle)
                     if !iconOnly { Text(settingsTitle) }
                 }
                 .tag(Tab.settings)
@@ -217,10 +236,30 @@ extension MainView {
                   hamburgerAction: hamburgerAction)
             }
 #endif
-          }
+          } .onNotification(.TransactionStateTransition) { notification in
+              // show an alert with the KYC link (button) which opens in Safari
+                if let transition = 
notification.userInfo?[TRANSACTIONTRANSITION] as? TransactionTransition {
+                    if transition.newTxState.major == .pending {
+                        if let newMinor = transition.newTxState.minor {
+                            if newMinor == .kyc {       // user did confirm on 
bank website
+                                logger.log(".onNotification(): KYC required")
+                                showKycAlert = true
+                            }
+                        }
+                    }
+                } else { // should never happen
+                    logger.error("Yikes! TransactionStateTransition without 
transition")
+//                    symLog.log(notification.userInfo as Any)
+                }
+            }
+            .alert("You need to pass a KYC procedure",
+                 isPresented: $showKycAlert,
+                 actions: {   openKycButton
+                              dismissAlertButton },
+                 message: {   Text("Tap the button to go to the KYC website.") 
})
             .onNotification(.BalanceChange) { notification in
               // reload balances on receiving BalanceChange notification ...
-                symLog?.log(".onNotification(.BalanceChange) ==> reload")
+                logger.info(".onNotification(.BalanceChange) ==> reload")
                 shouldReloadBalances += 1
             }
             .onChange(of: balances) { newArray in
diff --git a/TalerWallet1/Views/Main/WalletEmptyView.swift 
b/TalerWallet1/Views/Main/WalletEmptyView.swift
index c357f03..f38b657 100644
--- a/TalerWallet1/Views/Main/WalletEmptyView.swift
+++ b/TalerWallet1/Views/Main/WalletEmptyView.swift
@@ -19,9 +19,11 @@ struct WalletEmptyView: View {
                 Text("There is no digital cash in your wallet.")
                     .accessibilityFont(.title3)
                     .listRowSeparator(.hidden)
-                Link("Get some test money", destination: URL(string: 
DEMOBANK)!)
+                let title = String(localized: "LinkTitle_DEMOBANK", 
defaultValue: "Get some test money")
+                Link(title, destination: URL(string: DEMOBANK)!)
                     .buttonStyle(TalerButtonStyle(type: .prominent, narrow: 
false, aligned: .center))
                     .padding(.vertical)
+                    .accessibilityHint("Will go to the demo bank website.")
             }
             Section {
                 Text("Just register a test account in the demo bank, then 
withdraw some electronic cash.")
diff --git a/TalerWallet1/Views/Peer2peer/PaymentPurpose.swift 
b/TalerWallet1/Views/Peer2peer/PaymentPurpose.swift
index 42e919c..8b04c12 100644
--- a/TalerWallet1/Views/Peer2peer/PaymentPurpose.swift
+++ b/TalerWallet1/Views/Peer2peer/PaymentPurpose.swift
@@ -15,7 +15,10 @@ struct PaymentPurpose: View {
     let fee: String
     @Binding var summary: String
     @Binding var expireDays: UInt
+    @AppStorage("iconOnly") var iconOnly: Bool = false
+    let navTitle = String(localized: "NavTitle_Request_Subject", defaultValue: 
"Request", comment: "NavTitle for entering the subject for Request-Payment")
 
+    @State private var transactionStarted: Bool = false
     @FocusState private var isFocused: Bool
 
     private var label: String {
@@ -32,11 +35,12 @@ struct PaymentPurpose: View {
             Text("+ \(fee) payment fee")
                 .foregroundColor(.red)
             VStack(alignment: .leading, spacing: 6) {
-                Text("Purpose:")
-                    .padding(.top)
-                    .accessibilityFont(.title3)
-
-                TextField("Purpose", text: $summary)
+                if !iconOnly {
+                    Text("Subject:")
+                        .accessibilityFont(.title3)
+                        .padding(.top)
+                }
+                TextField("Subject", text: $summary)
                     .accessibilityFont(.title)
                     .foregroundColor(WalletColors().fieldForeground)     // 
text color
                     .background(WalletColors().fieldBackground)
@@ -53,37 +57,35 @@ struct PaymentPurpose: View {
                     Text(verbatim: "\(summary.count)/100")
                 } // maximum 100 characters
 
-                Text("Expires in:")
-                    .accessibilityFont(.title3)
-
                 SelectDays(selected: $expireDays, maxExpiration: THIRTYDAYS)
                     .disabled(false)
                     .padding(.bottom)
 
                 let disabled = (expireDays == 0) || (summary.count < 1)
-
                 NavigationLink(destination: LazyView {
-                    SendDone(stack: stack.push(),
-                      amountToSend: nil,
-                   amountToReceive: amount,
-                           summary: summary,
-                        expireDays: expireDays)
+                    SendDoneV(stack: stack.push(),
+                       amountToSend: nil,
+                    amountToReceive: amount,
+                            summary: summary,
+                         expireDays: expireDays,
+                 transactionStarted: $transactionStarted)
                 }) {
                     Text("Request \(label) \(scopeInfo.currency)")
 //                        .accessibilityFont(buttonFont)
                 }
                 .buttonStyle(TalerButtonStyle(type: .prominent))
                 .disabled(disabled)
+                .accessibilityHint(disabled ? "enabled when subject and 
expiration are set" : EMPTYSTRING)
 
                 Spacer()
             }
             .frame(maxWidth: .infinity, alignment: .leading)
             .padding(.horizontal)
         }
-        .navigationTitle("Request")
+        .navigationTitle(navTitle)
         .background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
         .onAppear {
-            DebugViewC.shared.setViewID(VIEW_RECEIVE_PURPOSE, stack: 
stack.push())
+            DebugViewC.shared.setViewID(VIEW_REQUEST_PURPOSE, stack: 
stack.push())
 //            print("❗️ PaymentPurpose onAppear")
         }
         .onDisappear {
diff --git a/TalerWallet1/Views/Peer2peer/RequestPayment.swift 
b/TalerWallet1/Views/Peer2peer/RequestPayment.swift
index 028dc1c..10cb313 100644
--- a/TalerWallet1/Views/Peer2peer/RequestPayment.swift
+++ b/TalerWallet1/Views/Peer2peer/RequestPayment.swift
@@ -62,7 +62,7 @@ struct RequestPayment: View {
         .background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
         .navigationTitle(navTitle)
         .onAppear {   // make CurrencyField show the keyboard
-            DebugViewC.shared.setViewID(VIEW_RECEIVE_P2P, stack: stack.push())
+            DebugViewC.shared.setViewID(VIEW_REQUEST_P2P, stack: stack.push())
             symLog.log("❗️Yikes \(navTitle) onAppear")
         }
         .onDisappear {
diff --git a/TalerWallet1/Views/Peer2peer/SendDone.swift 
b/TalerWallet1/Views/Peer2peer/SendDoneV.swift
similarity index 81%
rename from TalerWallet1/Views/Peer2peer/SendDone.swift
rename to TalerWallet1/Views/Peer2peer/SendDoneV.swift
index 5d09df6..84b31ee 100644
--- a/TalerWallet1/Views/Peer2peer/SendDone.swift
+++ b/TalerWallet1/Views/Peer2peer/SendDoneV.swift
@@ -7,8 +7,8 @@ import taler_swift
 import SymLog
 
 // Called when initiating a P2P transaction: Send coins or Send 
Request(Invoice)
-struct SendDone: View {
-    private let symLog = SymLogV(0)
+struct SendDoneV: View {
+    private let symLog = SymLogV()
     let stack: CallStack
     let navTitle = String(localized: "P2P Ready")
 #if DEBUG
@@ -22,10 +22,11 @@ struct SendDone: View {
     let amountToReceive: Amount?
     let summary: String
     let expireDays: UInt
+    @Binding var transactionStarted: Bool
 
     @EnvironmentObject private var model: WalletModel
 
-    @State private var transactionId: String?
+    @State private var transactionId: String? = nil
 
     func reloadOneAction(_ transactionId: String) async throws -> Transaction {
         return try await model.getTransactionByIdT(transactionId)
@@ -59,6 +60,12 @@ struct SendDone: View {
         .task {
             symLog.log(".task")
             do {
+                guard transactionStarted == false else {
+// TODO:               logger.warning("Try to start P2P a second time")
+                    symLog.log("Yikes❗️ Try to start P2P a second time")
+                    return
+                }
+                transactionStarted = true
                 let timestamp = developerMode ? 
Timestamp.inSomeMinutes(expireDays > 20 ? (24*60)
                                                                       : 
expireDays > 5 ? 60 : 3)
                                               : 
Timestamp.inSomeDays(expireDays)
@@ -86,14 +93,14 @@ struct SendDone: View {
     }
 }
 // MARK: -
-struct SendNow_Previews: PreviewProvider {
-    static var previews: some View {
-        Group {
-            SendDone(stack: CallStack("Preview"),
-              amountToSend: try! Amount(fromString: LONGCURRENCY + ":4.8"),
-           amountToReceive: nil,
-                   summary: "some purpose",
-                expireDays: 0)
-        }
-    }
-}
+//struct SendNow_Previews: PreviewProvider {
+//    static var previews: some View {
+//        Group {
+//            SendDoneV(stack: CallStack("Preview"),
+//              amountToSend: try! Amount(fromString: LONGCURRENCY + ":4.8"),
+//           amountToReceive: nil,
+//                   summary: "some subject/purpose",
+//                expireDays: 0)
+//        }
+//    }
+//}
diff --git a/TalerWallet1/Views/Peer2peer/SendPurpose.swift 
b/TalerWallet1/Views/Peer2peer/SendPurpose.swift
index bbe11af..06ba0a4 100644
--- a/TalerWallet1/Views/Peer2peer/SendPurpose.swift
+++ b/TalerWallet1/Views/Peer2peer/SendPurpose.swift
@@ -16,6 +16,10 @@ struct SendPurpose: View {
     let fee: String
     @Binding var summary: String
     @Binding var expireDays: UInt
+    @AppStorage("iconOnly") var iconOnly: Bool = false
+    let navTitle = String(localized: "NavTitle_Send_Subject", defaultValue: 
"Subject", comment: "NavTitle for entering the subject for Send-Money")
+
+    @State private var transactionStarted: Bool = false
 
     private var value: String {
 //        let mag = pow(10, formatter.maximumFractionDigits)
@@ -32,12 +36,13 @@ struct SendPurpose: View {
                 .accessibilityFont(.body)
                 .foregroundColor(.red)
             VStack(alignment: .leading, spacing: 6) {
-                Text("Purpose:")
-                    .accessibilityFont(.title2)
-                    .padding(.top)
-
+                if !iconOnly {
+                    Text("Subject:")    // Purpose
+                        .accessibilityFont(.title2)
+                        .padding(.top)
+                }
                 if #available(iOS 16.0, *) {
-                    TextField("Purpose", text: $summary, axis: .vertical)
+                    TextField("Subject", text: $summary, axis: .vertical)
                         .accessibilityFont(.title2)
                         .lineLimit(2...)
                         .foregroundColor(WalletColors().fieldForeground)     
// text color
@@ -50,7 +55,7 @@ struct SendPurpose: View {
                             }
                         }
                 } else {
-                    TextField("Purpose", text: $summary)
+                    TextField("Subject", text: $summary)
                         .accessibilityFont(.title)
 //                        .lineLimit(2...5)   // lineLimit' is only available 
in iOS 16.0 or newer
                         .foregroundColor(WalletColors().fieldForeground)     
// text color
@@ -62,35 +67,34 @@ struct SendPurpose: View {
                                 isFocused = true        // make first 
responder - raise keybord
                             }
                         }
-                }
+                } // #available
 
                 HStack{
                     Spacer()
                     Text(verbatim: "\(summary.count)/100")
                         .accessibilityFont(.body)
+                        .accessibilityValue("\(summary.count) characters of 
100")
                 } // maximum 100 characters
 
-                Text("Expires in:")
-                    .accessibilityFont(.title3)
-
                 // TODO: compute max Expiration day from peerPushCheck to 
disable 30 (and even 7)
                 SelectDays(selected: $expireDays, maxExpiration: THIRTYDAYS)
                     .disabled(false)
                     .padding(.bottom)
 
                 let disabled = (expireDays == 0) || (summary.count < 1)    // 
TODO: check amountAvailable
-
                 NavigationLink(destination: LazyView {
-                    SendDone(stack: stack.push(),
-                      amountToSend: amount,
-                   amountToReceive: nil,
-                           summary: summary,
-                        expireDays: expireDays)
+                    SendDoneV(stack: stack.push(),
+                       amountToSend: amount,
+                    amountToReceive: nil,
+                            summary: summary,
+                         expireDays: expireDays,
+                 transactionStarted: $transactionStarted)
                 }) {
                     Text("Send \(value) \(amountAvailable.currencyStr) now", 
comment: "first is value, second currencyString")  // TODO: currency formatter
                 }
                 .buttonStyle(TalerButtonStyle(type: .prominent))
                 .disabled(disabled)
+                .accessibilityHint(disabled ? "enabled when subject and 
expiration are set" : EMPTYSTRING)
 
                 Spacer()
             }
@@ -98,7 +102,7 @@ struct SendPurpose: View {
             .frame(maxWidth: .infinity, alignment: .leading)
             .padding(.horizontal)
         }
-        .navigationTitle("Purpose")
+        .navigationTitle(navTitle)
         .background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
         .onAppear {
             DebugViewC.shared.setViewID(VIEW_SEND_PURPOSE, stack: stack.push())
diff --git a/TalerWallet1/Views/Settings/AboutView.swift 
b/TalerWallet1/Views/Settings/AboutView.swift
index 8a388ac..2e460bf 100644
--- a/TalerWallet1/Views/Settings/AboutView.swift
+++ b/TalerWallet1/Views/Settings/AboutView.swift
@@ -35,6 +35,7 @@ struct AboutView: View {
                     HStack {
                         Spacer()
                         RotatingTaler(size: 100, rotationEnabled: 
$rotationEnabled)
+                            .accessibilityHint("Will go to the taler.net 
website when long-pressed.")
                             .onTapGesture(count: 2) {
                                 rotationEnabled.toggle()
                             }
diff --git a/TalerWallet1/Views/Settings/SettingsItem.swift 
b/TalerWallet1/Views/Settings/SettingsItem.swift
index 76220e0..61220e7 100644
--- a/TalerWallet1/Views/Settings/SettingsItem.swift
+++ b/TalerWallet1/Views/Settings/SettingsItem.swift
@@ -35,7 +35,8 @@ struct SettingsItem<Content: View>: View {
             content()
                 .accessibilityFont(.body)
         }.id(id1 == nil ? nil : id1! + "_H")
-        .padding([.bottom], 4)
+            .accessibilityElement(children: .combine)
+            .padding([.bottom], 4)
     }
 }
 // MARK: -
@@ -47,9 +48,16 @@ struct SettingsToggle: View {
     var action: () -> Void = {}
 
     var body: some View {
+        let accLabel: String = if let description {
+            name + ", " + description
+        } else {
+            name
+        }
         VStack {
             Toggle(name, isOn: $value.animation())
                 .id(id1)
+//                .accessibilityLabel(name)
+                .accessibility(sortPriority: 1)
                 .accessibilityFont(.title2)
                 .onChange(of: value) { value in
                     action()
@@ -59,9 +67,12 @@ struct SettingsToggle: View {
                 Text(desc)
                     .id(id1 == nil ? nil : id1! + "_T")
                     .frame(maxWidth: .infinity, alignment: .leading)
+                    .accessibility(sortPriority: 0)
                     .accessibilityFont(.caption)
             }
         }
+        .accessibilityElement(children: .combine)
+        .accessibilityLabel(accLabel)
         .padding([.bottom], 4)
         .id(id1 == nil ? nil : id1! + "_V")
     }
@@ -111,6 +122,7 @@ struct SettingsStyle: View {
 //                .frame(alignment: .trailing)
 //                .background(WalletColors().buttonBackColor(pressed: false, 
disabled: false))  TODO: RoundRect
         }
+        .accessibilityElement(children: .combine)
     }
 }
 // MARK: -
@@ -121,42 +133,46 @@ struct SettingsSpeaker: View {
     var action: (_ value: Int) -> Void = {value in }
 
     func imageName(_ value: Int) -> (String, String) {
-        return (value == 0) ? ("speaker.slash", String(localized:"off", 
comment: "Accessibility String for Payment Sounds Off"))
-             : (value == 1) ? ("speaker.fill", String(localized:"Taler 
Sounds", comment: "Accessibility String for Payment Sounds"))
-                            : ("speaker", String(localized:"Apple Sounds", 
comment: "Accessibility String for Payment Sounds"))
+        return (value == 0) ? ("speaker.slash", String(localized:"Off",        
  comment: "Accessibility String for Payment Sounds."))
+             : (value == 1) ? ("speaker.fill",  String(localized:"Taler 
Sounds", comment: "Accessibility String for Payment Sounds."))
+                            : ("speaker",       String(localized:"Apple 
Sounds", comment: "Accessibility String for Payment Sounds."))
     }
     var body: some View {
+        let image = imageName(value)
+        let accHint = description ?? ""         // avoid automatic translation 
of "" in accessibilityHint
+
         VStack {
-            let image = imageName(value)
             HStack {
                 Text(name)
                     .accessibilityFont(.title2)
-                Text(" ")
+                Text(verbatim: " ")
                     .accessibilityFont(.largeTitle)
                 Spacer()
-                Image(systemName: image.0)
-                    .accessibilityFont(.largeTitle)
-                    .accessibilityLabel(image.1)
-                    .onTapGesture {
-                        if value > 0 {
-                            value = -1
-                            Controller.shared.playSound(1)
-                        } else {
-                            value = value + 1
-                            Controller.shared.playSound(value)
-                        }
+                Button {
+                    if value > 0 {
+                        value = -1
+                        Controller.shared.playSound(1)
+                    } else {
+                        value = value + 1
+                        Controller.shared.playSound(value)
                     }
+                } label: {
+                    Image(systemName: image.0)
+                        .accessibilityFont(.largeTitle)
+                }
             }
-//                .onChange(of: value) { value in
-//                    action(value)
-//                }
 
             if let desc = description {
                 Text(desc)
                     .frame(maxWidth: .infinity, alignment: .leading)
                     .accessibilityFont(.caption)
             }
-        }.padding([.bottom], 4)
+        }
+        .accessibilityElement(children: .combine)
+        .accessibilityLabel(name)
+        .accessibility(value: Text(image.1))
+        .accessibilityHint(accHint)
+        .padding([.bottom], 4)
     }
 }
 // MARK: -
diff --git a/TalerWallet1/Views/Settings/SettingsView.swift 
b/TalerWallet1/Views/Settings/SettingsView.swift
index af94378..40abcc2 100644
--- a/TalerWallet1/Views/Settings/SettingsView.swift
+++ b/TalerWallet1/Views/Settings/SettingsView.swift
@@ -28,8 +28,9 @@ struct SettingsView: View {
 #else
     @AppStorage("developerMode") var developerMode: Bool = false
 #endif
-    @AppStorage("useHaptics") var useHaptics: Bool = false
-    @AppStorage("playSounds") var playSounds: Int = 0
+//    @AppStorage("moreContrast") var moreContrast: Bool = false
+    @AppStorage("useHaptics") var useHaptics: Bool = true
+    @AppStorage("playSounds") var playSounds: Int = 1
     @AppStorage("talerFont") var talerFont: Int = 0
     @AppStorage("developDelay") var developDelay: Bool = false
     @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
@@ -101,6 +102,8 @@ struct SettingsView: View {
                     SettingsItem(name: aboutStr, id1: "about",
                           description: hideDescriptions ? nil : 
String(localized: "More info about this app...")) {}
                 }
+//                SettingsToggle(name: String(localized: "More Contrast"), 
value: $moreContrast, id1: "contrast",
+//                               description: hideDescriptions ? nil : 
String(localized: "If you don't like grey"))
                 if controller.hapticCapability.supportsHaptics {
                     SettingsToggle(name: String(localized: "Haptics"), value: 
$useHaptics, id1: "haptics",
                             description: hideDescriptions ? nil : 
String(localized: "Vibration Feedback"))
@@ -115,24 +118,25 @@ struct SettingsView: View {
                     hideDescriptions = iconOnly //withAnimation { 
hideDescriptions = iconOnly }
                 }
                 if diagnosticModeEnabled {
-                    SettingsToggle(name: String(localized: "Developer Mode"), 
value: $developerMode, id1: "devMode",
-                            description: hideDescriptions ? nil : 
String(localized: "More information intended for debugging")) {
+                    SettingsToggle(name: String("Developer Mode"), value: 
$developerMode, id1: "devMode",
+                            description: hideDescriptions ? nil : String("More 
information intended for debugging")) {
                         withAnimation { showDevelopItems = developerMode }
                     }
                     if showDevelopItems {  // show or hide the following items
                         NavigationLink {        // whole row like in a 
tableView
                             LazyView { PendingOpsListView(stack: stack.push()) 
}
                         } label: {
-                            SettingsItem(name: String(localized: "Pending 
Operations"), id1: "pending",
-                                  description: hideDescriptions ? nil : 
String(localized: "Exchange not yet ready...")) {}
+                            SettingsItem(name: String("Pending Operations"), 
id1: "pending",
+                                  description: hideDescriptions ? nil : 
String("Transactions not yet done...")) {}
                         }.id("pending_L")
-                        SettingsToggle(name: String(localized: "Set 2 seconds 
delay"),
+                        SettingsToggle(name: String("Set 2 seconds delay"),
                                       value: $developDelay.onChange({ delay in
                                         walletCore.developDelay = delay}), 
id1: "delay",
-                                description: hideDescriptions ? nil : 
String(localized: "After each wallet-core action"))
-                        SettingsItem(name: String(localized: "Withdraw 
\(DEMOCURRENCY)"), id1: "demo1with",
-                              description: hideDescriptions ? nil : 
String(localized: "Get money for testing")) {
-                            Button("Withdraw") {
+                                description: hideDescriptions ? nil : 
String("After each wallet-core action"))
+                        SettingsItem(name: String("Withdraw \(DEMOCURRENCY)"), 
id1: "demo1with",
+                              description: hideDescriptions ? nil : 
String("Get money for testing")) {
+                            let title = "Withdraw"
+                            Button(title) {
                                 withDrawDisabled = true    // don't run twice
                                 Task { // runs on MainActor
                                     symLog.log("Withdraw KUDOS")
@@ -146,9 +150,10 @@ struct SettingsView: View {
                             .buttonStyle(.bordered)
                             .disabled(withDrawDisabled)
                         }.id("demoWithdraw")
-                        SettingsItem(name: String(localized: "Withdraw 
\(TESTCURRENCY)"), id1: "test1with",
-                              description: hideDescriptions ? nil : 
String(localized: "Get money for testing")) {
-                            Button("Withdraw") {
+                        SettingsItem(name: String("Withdraw \(TESTCURRENCY)"), 
id1: "test1with",
+                              description: hideDescriptions ? nil : 
String("Get money for testing")) {
+                            let title = "Withdraw"
+                            Button(title) {
                                 withDrawDisabled = true    // don't run twice
                                 Task { // runs on MainActor
                                     symLog.log("Withdraw TESTKUDOS")
@@ -162,9 +167,10 @@ struct SettingsView: View {
                             .buttonStyle(.bordered)
                             .disabled(withDrawDisabled)
                         }.id("testWithdraw")
-                        SettingsItem(name: String(localized: "Run Integration 
Test"), id1: "demo1test",
-                              description: hideDescriptions ? nil : 
String(localized: "Perform basic test transactions")) {
-                            Button("Demo 1") {
+                        SettingsItem(name: String("Run Integration Test"), 
id1: "demo1test",
+                              description: hideDescriptions ? nil : 
String("Perform basic test transactions")) {
+                            let title = "Demo 1"
+                            Button(title) {
                                 checkDisabled = true    // don't run twice
                                 Task { // runs on MainActor
                                     symLog.log("running integration test on 
demo")
@@ -178,9 +184,10 @@ struct SettingsView: View {
                             .buttonStyle(.bordered)
                             .disabled(checkDisabled)
                         }
-                        SettingsItem(name: String(localized: "Run Integration 
Test"), id1: "test1test",
-                              description: hideDescriptions ? nil : 
String(localized: "Perform basic test transactions")) {
-                            Button("Test 1") {
+                        SettingsItem(name: String("Run Integration Test"), 
id1: "test1test",
+                              description: hideDescriptions ? nil : "Perform 
basic test transactions") {
+                            let title = "Test 1"
+                            Button(title) {
                                 checkDisabled = true    // don't run twice
                                 Task { // runs on MainActor
                                     symLog.log("running integration test on 
test")
@@ -194,9 +201,10 @@ struct SettingsView: View {
                             .buttonStyle(.bordered)
                             .disabled(checkDisabled)
                         }
-                        SettingsItem(name: String(localized: "Run Integration 
Test V2"), id1: "demo2test",
-                              description: hideDescriptions ? nil : 
String(localized: "Perform more test transactions")) {
-                            Button("Demo 2") {
+                        SettingsItem(name: String("Run Integration Test V2"), 
id1: "demo2test",
+                              description: hideDescriptions ? nil : 
String("Perform more test transactions")) {
+                            let title = "Demo 2"
+                            Button(title) {
                                 checkDisabled = true    // don't run twice
                                 Task { // runs on MainActor
                                     symLog.log("running integration test V2 on 
demo")
@@ -210,9 +218,10 @@ struct SettingsView: View {
                             .buttonStyle(.bordered)
                             .disabled(checkDisabled)
                         }
-                        SettingsItem(name: String(localized: "Run Integration 
Test V2"), id1: "test2test",
-                              description: hideDescriptions ? nil : 
String(localized: "Perform more test transactions")) {
-                            Button("Test 2") {
+                        SettingsItem(name: String("Run Integration Test V2"), 
id1: "test2test",
+                              description: hideDescriptions ? nil : 
String("Perform more test transactions")) {
+                            let title = "Test 2"
+                            Button(title) {
                                 checkDisabled = true    // don't run twice
                                 Task { // runs on MainActor
                                     symLog.log("running integration test V2 on 
test")
@@ -226,8 +235,8 @@ struct SettingsView: View {
                             .buttonStyle(.bordered)
                             .disabled(checkDisabled)
                         }
-                        SettingsItem(name: String(localized: "Save Logfile"), 
id1: "save",
-                              description: hideDescriptions ? nil : 
String(localized: "Help debugging wallet-core")) {
+                        SettingsItem(name: String("Save Logfile"), id1: "save",
+                              description: hideDescriptions ? nil : 
String("Help debugging wallet-core")) {
                             Button("Save") {
                                 symLog.log("Saving Log")
                                 // FIXME: Save Logfile
@@ -235,8 +244,8 @@ struct SettingsView: View {
                             .buttonStyle(.bordered)
                             .disabled(true)
                         }
-                        SettingsItem(name: String(localized: "Reset Wallet"), 
id1: "reset",
-                              description: hideDescriptions ? nil : 
String(localized: "Throw away all your money")) {
+                        SettingsItem(name: String("Reset Wallet"), id1: 
"reset",
+                              description: hideDescriptions ? nil : 
String("Throw away all your money")) {
                             Button("Reset") {
                                 showResetAlert = true
                             }
@@ -264,7 +273,7 @@ struct SettingsView: View {
                isPresented: $showResetAlert,
                actions: { dismissAlertButton
                           resetButton },
-               message: {   Text("Are you sure you want to reset your 
wallet?\nThis cannot be reverted, all money will be lost.") })
+               message: {   Text(verbatim: "Are you sure you want to reset 
your wallet?\nThis cannot be reverted, all money will be lost.") })
 
 #if !DEBUG
         .onReceive(
diff --git a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift 
b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift
index 905670d..9e9ccc6 100644
--- a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift
+++ b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift
@@ -29,14 +29,14 @@ struct P2pPayURIView: View {
                     let effective = peerPullDebitResponse.amountEffective
                     let currency = raw.currencyStr
                     let fee = try! Amount.diff(raw, effective)
-                    ThreeAmountsView(topTitle: String(localized: "Amount to 
pay:"),
-                                    topAbbrev: String(localized: "Pay:"),
-                                    topAmount: raw, fee: fee,
-                                  bottomTitle: String(localized: "Amount to be 
spent:"),
-                                 bottomAbbrev: String(localized: "Effective:"),
-                                 bottomAmount: effective,
-                                        large: false, pending: false, 
incoming: false,
-                                      baseURL: nil)
+                    ThreeAmountsV(topTitle: String(localized: "Amount to 
pay:"),
+                                 topAbbrev: String(localized: "Pay:"),
+                                 topAmount: raw, fee: fee,
+                               bottomTitle: String(localized: "Amount to be 
spent:"),
+                              bottomAbbrev: String(localized: "Effective:"),
+                              bottomAmount: effective,
+                                     large: false, pending: false, incoming: 
false,
+                                   baseURL: nil)
                 }
                 .listStyle(myListStyle.style).anyView
                 .navigationTitle(navTitle)
diff --git a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift 
b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift
index d8521e5..d856947 100644
--- a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift
+++ b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift
@@ -29,14 +29,14 @@ struct P2pReceiveURIView: View {
                     let effective = peerPushCreditResponse.amountEffective
                     let currency = raw.currencyStr
                     let fee = try! Amount.diff(raw, effective)
-                    ThreeAmountsView(topTitle: String(localized: "Amount to 
receive:"),
-                                    topAbbrev: String(localized: "Receive:"),
-                                    topAmount: raw, fee: fee,
-                                  bottomTitle: String(localized: "Amount to be 
obtained:"),
-                                 bottomAbbrev: String(localized: "Effective:"),
-                                 bottomAmount: effective,
-                                        large: false, pending: false, 
incoming: true,
-                                      baseURL: nil)
+                    ThreeAmountsV(topTitle: String(localized: "Amount to 
receive:"),
+                                 topAbbrev: String(localized: "Receive:"),
+                                 topAmount: raw, fee: fee,
+                               bottomTitle: String(localized: "Amount to 
obtain:"),
+                              bottomAbbrev: String(localized: "Effective:"),
+                              bottomAmount: effective,
+                                     large: false, pending: false, incoming: 
true,
+                                   baseURL: nil)
                 }
                 .listStyle(myListStyle.style).anyView
                 .navigationTitle(navTitle)
diff --git a/TalerWallet1/Views/Sheets/Payment/PayTemplateView.swift 
b/TalerWallet1/Views/Sheets/Payment/PayTemplateView.swift
index e626cc2..7dda920 100644
--- a/TalerWallet1/Views/Sheets/Payment/PayTemplateView.swift
+++ b/TalerWallet1/Views/Sheets/Payment/PayTemplateView.swift
@@ -60,26 +60,26 @@ struct PayTemplateView: View {
                 if let effective {
                     // TODO: already paid
                     let fee = try! Amount.diff(raw, effective)      // TODO: 
different currencies
-                    ThreeAmountsView(topTitle: topTitle,
-                                    topAbbrev: topAbbrev,
-                                    topAmount: raw, fee: fee,
-                                  bottomTitle: String(localized: "Amount to be 
spent:"),
-                                 bottomAbbrev: String(localized: "Effective:"),
-                                 bottomAmount: effective,
-                                        large: false, pending: false, 
incoming: false,
-                                      baseURL: baseURL)
+                    ThreeAmountsV(topTitle: topTitle,
+                                 topAbbrev: topAbbrev,
+                                 topAmount: raw, fee: fee,
+                               bottomTitle: String(localized: "Amount to 
spend:"),
+                              bottomAbbrev: String(localized: "Effective:"),
+                              bottomAmount: effective,
+                                     large: false, pending: false, incoming: 
false,
+                                   baseURL: baseURL)
                     // TODO: payment: popup with all possible exchanges, check 
fees
                 } else if let balanceDetails = preparePayResult.balanceDetails 
{    // Insufficient
                     Text("You don't have enough \(currency)")
                         .accessibilityFont(.body)
-                    ThreeAmountsView(topTitle: topTitle,
-                                    topAbbrev: topAbbrev,
-                                    topAmount: raw, fee: nil,
-                                  bottomTitle: String(localized: "Amount 
available:"),
-                                 bottomAbbrev: String(localized: "Available:"),
-                                 bottomAmount: balanceDetails.balanceAvailable,
-                                        large: false, pending: false, 
incoming: false,
-                                      baseURL: baseURL)
+                    ThreeAmountsV(topTitle: topTitle,
+                                 topAbbrev: topAbbrev,
+                                 topAmount: raw, fee: nil,
+                               bottomTitle: String(localized: "Amount 
available:"),
+                              bottomAbbrev: String(localized: "Available:"),
+                              bottomAmount: balanceDetails.balanceAvailable,
+                                     large: false, pending: false, incoming: 
false,
+                                   baseURL: baseURL)
                 } else {
                     // TODO: Error - neither effective nor balanceDetails
                     Text("Error")
diff --git a/TalerWallet1/Views/Sheets/Payment/PaymentView.swift 
b/TalerWallet1/Views/Sheets/Payment/PaymentView.swift
index 7a14aeb..27557b7 100644
--- a/TalerWallet1/Views/Sheets/Payment/PaymentView.swift
+++ b/TalerWallet1/Views/Sheets/Payment/PaymentView.swift
@@ -53,26 +53,26 @@ struct PaymentView: View {
                 if let effective {
                     // TODO: already paid
                     let fee = try! Amount.diff(raw, effective)      // TODO: 
different currencies
-                    ThreeAmountsView(topTitle: topTitle,
-                                    topAbbrev: topAbbrev,
-                                    topAmount: raw, fee: fee,
-                                  bottomTitle: String(localized: "Amount to be 
spent:"),
-                                 bottomAbbrev: String(localized: "Effective:"),
-                                 bottomAmount: effective,
-                                        large: false, pending: false, 
incoming: false,
-                                      baseURL: baseURL)
+                    ThreeAmountsV(topTitle: topTitle,
+                                 topAbbrev: topAbbrev,
+                                 topAmount: raw, fee: fee,
+                               bottomTitle: String(localized: "Amount to 
spend:"),
+                              bottomAbbrev: String(localized: "Effective:"),
+                              bottomAmount: effective,
+                                     large: false, pending: false, incoming: 
false,
+                                   baseURL: baseURL)
                     // TODO: payment: popup with all possible exchanges, check 
fees
                 } else if let balanceDetails = preparePayResult.balanceDetails 
{    // Insufficient
                     Text("You don't have enough \(currency)")
                         .accessibilityFont(.body)
-                    ThreeAmountsView(topTitle: topTitle,
-                                    topAbbrev: topAbbrev,
-                                    topAmount: raw, fee: nil,
-                                  bottomTitle: String(localized: "Available:"),
-                                 bottomAbbrev: String(localized: "Available:"),
-                                 bottomAmount: balanceDetails.balanceAvailable,
-                                        large: false, pending: false, 
incoming: false,
-                                      baseURL: baseURL)
+                    ThreeAmountsV(topTitle: topTitle,
+                                 topAbbrev: topAbbrev,
+                                 topAmount: raw, fee: nil,
+                               bottomTitle: String(localized: "Amount 
available:"),
+                              bottomAbbrev: String(localized: "Available:"),
+                              bottomAmount: balanceDetails.balanceAvailable,
+                                     large: false, pending: false, incoming: 
false,
+                                   baseURL: baseURL)
                 } else {
                     // TODO: Error - neither effective nor balanceDetails
                     Text("Error")
diff --git a/TalerWallet1/Views/Sheets/Sheet.swift 
b/TalerWallet1/Views/Sheets/Sheet.swift
index b1f0cda..371d110 100644
--- a/TalerWallet1/Views/Sheets/Sheet.swift
+++ b/TalerWallet1/Views/Sheets/Sheet.swift
@@ -42,6 +42,8 @@ struct Sheet: View {
                 .monospacedDigit()
                 .edgesIgnoringSafeArea(.top)
                 .id("sheetID")
+                .accessibilityLabel(Text("Sheet.ID.", comment: 
"AccessibilityLabel"))
+                .accessibilityValue(idString)
         }
     }
 }
diff --git 
a/TalerWallet1/Views/Sheets/WithdrawBankIntegrated/WithdrawURIView.swift 
b/TalerWallet1/Views/Sheets/WithdrawBankIntegrated/WithdrawURIView.swift
index 89eda47..2fb147e 100644
--- a/TalerWallet1/Views/Sheets/WithdrawBankIntegrated/WithdrawURIView.swift
+++ b/TalerWallet1/Views/Sheets/WithdrawBankIntegrated/WithdrawURIView.swift
@@ -36,17 +36,19 @@ struct WithdrawURIView: View {
                     let outColor = WalletColors().transactionColor(false)
                     let inColor = WalletColors().transactionColor(true)
 
-                    ThreeAmountsView(topTitle: String(localized: "Chosen 
amount to withdraw:"),
-                                    topAbbrev: String(localized: "Chosen:"),
-                                    topAmount: raw, fee: fee,
-                                  bottomTitle: String(localized: "Amount to be 
withdrawn:"),
-                                 bottomAbbrev: String(localized: "Effective:"),
-                                 bottomAmount: effective,
-                                        large: false, pending: false, 
incoming: true,
-                                      baseURL: exchangeBaseUrl)
+                    ThreeAmountsV(topTitle: String(localized: "Chosen amount 
to withdraw:"),
+                                 topAbbrev: String(localized: "Chosen:"),
+                                 topAmount: raw, fee: fee,
+                               bottomTitle: String(localized: "Amount to be 
withdrawn:"),
+                              bottomAbbrev: String(localized: "Effective:"),
+                              bottomAmount: effective,
+                                     large: false, pending: false, incoming: 
true,
+                                   baseURL: exchangeBaseUrl)
                     let someCoins = SomeCoins(details: withdrawalAmountDetails)
-                    QuiteSomeCoins(someCoins: someCoins, shouldShowFee: false,
-                                   currency: raw.currencyStr, amountEffective: 
effective)
+                    QuiteSomeCoins(someCoins: someCoins,
+                               shouldShowFee: true,           // TODO: set to 
false if we never charge withdrawal fees
+                                    currency: raw.currencyStr,
+                             amountEffective: effective)
                 }
                 .listStyle(myListStyle.style).anyView
                 .navigationTitle(navTitle)
diff --git a/TalerWallet1/Views/Transactions/ManualDetails.swift 
b/TalerWallet1/Views/Transactions/ManualDetailsV.swift
similarity index 66%
rename from TalerWallet1/Views/Transactions/ManualDetails.swift
rename to TalerWallet1/Views/Transactions/ManualDetailsV.swift
index adc9e15..3adceaf 100644
--- a/TalerWallet1/Views/Transactions/ManualDetails.swift
+++ b/TalerWallet1/Views/Transactions/ManualDetailsV.swift
@@ -5,9 +5,12 @@
 import SwiftUI
 import taler_swift
 
-struct ManualDetails: View {
+struct ManualDetailsV: View {
     var common : TransactionCommon
     var details : WithdrawalDetails
+
+    @AppStorage("iconOnly") var iconOnly: Bool = false
+
     var body: some View {
         if let paytoUris = details.exchangePaytoUris {
             let payto = paytoUris[0]
@@ -15,10 +18,18 @@ struct ManualDetails: View {
             let iban = payURL?.iban ?? "unknown IBAN"
             let amount = common.amountRaw.readableDescription
             Group {
-                Text("You need to transfer \(amount) from your regular bank 
account to the Exchange.")
-                Text("Step 1: Copy this code and paste it into the 
subject/purpose field in your banking app or bank website.\nThis is mandatory, 
otherwise your money will not arrive in this wallet.")
-                    .multilineTextAlignment(.leading)
-                    .listRowSeparator(.hidden)
+                Text(iconOnly ? "Transfer \(amount) to the Exchange."
+                              : "You need to transfer \(amount) from your 
regular bank account to the Exchange.")
+                Text(iconOnly ? "Step 1: Copy+Paste this subject:"
+                              : "Step 1: Copy this code and paste it into the 
subject/purpose field in your banking app or bank website:")
+                        .multilineTextAlignment(.leading)
+                        .listRowSeparator(.hidden)
+                if !iconOnly {
+                    Text("This is mandatory, otherwise your money will not 
arrive in this wallet.")
+                        .bold()
+                        .multilineTextAlignment(.leading)
+                        .listRowSeparator(.hidden)
+                }
                 HStack {
                     Text(details.reservePub)
                         .monospacedDigit()
@@ -29,12 +40,14 @@ struct ManualDetails: View {
                         .disabled(false)
                 }   .padding(.leading)
                     .listRowSeparator(.hidden)
-                Text("Step 2: If you don't already have it in your banking 
favourites list, then copy and paste this IBAN into the receiver IBAN field in 
your banking app or website:")
+                Text(iconOnly ? "Step 2: Copy+Paste this IBAN:"
+                              : "Step 2: If you don't already have it in your 
banking favourites list, then copy and paste this IBAN into the receiver IBAN 
field in your banking app or website:")
                     .multilineTextAlignment(.leading)
                     .listRowSeparator(.hidden)
                 HStack {
                     Text(iban)
                         .monospacedDigit()
+                        .accessibilityLabel("IBAN of the exchange")
                     Spacer()
                     CopyButton(textToCopy: iban, vertical: true)
                         .accessibilityLabel("Copy the IBAN")
@@ -42,10 +55,12 @@ struct ManualDetails: View {
                 }   .padding(.leading)
                     .padding(.top, -8)
                     .listRowSeparator(.hidden)
-                Text("Step 3: Finish the wire transfer of \(amount) in your 
banking app or website, then this withdrawal will proceed automatically.")
+                Text(iconOnly ? "Step 3: Transfer \(amount)."
+                              : "Step 3: Finish the wire transfer of \(amount) 
in your banking app or website, then this withdrawal will proceed 
automatically.")
                     .multilineTextAlignment(.leading)
                     .listRowSeparator(.visible)
-                Text("Alternative: If your bank already supports PayTo, you 
can use this PayTo-Link instead:")
+                Text(iconOnly ? "Or use this PayTo-Link:"
+                              : "Alternative: If your bank already supports 
PayTo, you can use this PayTo-Link instead:")
                     .multilineTextAlignment(.leading)
                     .padding(.top, 2)
                     .listRowSeparator(.hidden)
@@ -78,7 +93,7 @@ struct ManualDetails_Previews: PreviewProvider {
         let details = WithdrawalDetails(type: .manual, reservePub: 
"ReSeRvEpUbLiC_KeY_FoR_WiThDrAwAl", reserveIsReady: false,
                                         
exchangePaytoUris:["payto://iban/SANDBOXX/DE159593?receiver-name=Exchange+Company"])
         List {
-            ManualDetails(common: common, details: details)
+            ManualDetailsV(common: common, details: details)
         }
     }
 }
diff --git a/TalerWallet1/Views/Transactions/ThreeAmounts.swift 
b/TalerWallet1/Views/Transactions/ThreeAmountsV.swift
similarity index 78%
rename from TalerWallet1/Views/Transactions/ThreeAmounts.swift
rename to TalerWallet1/Views/Transactions/ThreeAmountsV.swift
index ef77848..2579b94 100644
--- a/TalerWallet1/Views/Transactions/ThreeAmounts.swift
+++ b/TalerWallet1/Views/Transactions/ThreeAmountsV.swift
@@ -19,7 +19,9 @@ struct ThreeAmountsSheet: View {
         let effective = common.amountEffective
         let fee = common.fee()
         let incoming = common.incoming()
-        let pending = (common.txState.major == TransactionMajorState.pending)
+        let pending = (common.txState.major == .pending)
+        let isDone = (common.txState.major == .done)
+        let incomplete = !(isDone || pending)
 
         let defaultBottomTitle = incoming ? (pending ? String(localized: 
"Pending amount to obtain:")
                                                      : String(localized: 
"Obtained amount:") )
@@ -27,24 +29,24 @@ struct ThreeAmountsSheet: View {
         let defaultBottomAbbre = incoming ? (pending ? String(localized: 
"Pending:")
                                                      : String(localized: 
"Obtained:") )
                                           :            String(localized: 
"Paid:")
-        ThreeAmountsView(topTitle: topTitle, topAbbrev: topAbbrev, topAmount: 
raw, fee: fee,
-                      bottomTitle: bottomTitle ?? defaultBottomTitle,
-                     bottomAbbrev: bottomAbbrev ?? defaultBottomAbbre,
-                     bottomAmount: effective,
-                            large: large, pending: pending, incoming: incoming,
-                          baseURL: baseURL,
-                           status: common.txState.major.localizedState)
+        ThreeAmountsV(topTitle: topTitle, topAbbrev: topAbbrev, topAmount: 
raw, fee: fee,
+                   bottomTitle: bottomTitle ?? defaultBottomTitle,
+                  bottomAbbrev: bottomAbbrev ?? defaultBottomAbbre,
+                  bottomAmount: incomplete ? nil : effective,
+                         large: large, pending: pending, incoming: incoming,
+                       baseURL: baseURL,
+                        status: common.txState.major.localizedState)
     }
 }
 // MARK: -
-struct ThreeAmountsView: View {
+struct ThreeAmountsV: View {
     var topTitle: String
     var topAbbrev: String
     var topAmount: Amount
     var fee: Amount?
     var bottomTitle: String
     var bottomAbbrev: String
-    var bottomAmount: Amount
+    var bottomAmount: Amount?
     let large: Bool
     let pending: Bool
     let incoming: Bool
@@ -63,6 +65,7 @@ struct ThreeAmountsView: View {
                        color: labelColor,
                        large: large)
                 .padding(.bottom, 4)
+                .accessibilityElement(children: .combine)
             if let fee {
                 AmountView(title: iconOnly ? String(localized: "Fee:")
                                            : String(localized: "Exchange 
fee:"),
@@ -70,11 +73,15 @@ struct ThreeAmountsView: View {
                            color: labelColor,
                            large: false)
                 .padding(.bottom, 4)
+                .accessibilityElement(children: .combine)
+            }
+            if let bottomAmount {
+                AmountView(title: iconOnly ? bottomAbbrev : bottomTitle,
+                           value: bottomAmount.readableDescription,
+                           color: foreColor,
+                           large: large)
+                .accessibilityElement(children: .combine)
             }
-            AmountView(title: iconOnly ? bottomAbbrev : bottomTitle,
-                       value: bottomAmount.readableDescription,
-                       color: foreColor,
-                       large: large)
             if let baseURL {
                 VStack(alignment: .leading) {
                     Text(iconOnly ? "Exchange:" : "Using Exchange:")
@@ -92,6 +99,7 @@ struct ThreeAmountsView: View {
                 .padding(.top, 4)
                 .frame(maxWidth: .infinity, alignment: .leading)
                 .listRowSeparator(.hidden)
+                .accessibilityElement(children: .combine)
             }
         } header: {
             if !iconOnly {
diff --git a/TalerWallet1/Views/Transactions/TransactionDetailView.swift 
b/TalerWallet1/Views/Transactions/TransactionDetailView.swift
index 2da1d91..aca9ae8 100644
--- a/TalerWallet1/Views/Transactions/TransactionDetailView.swift
+++ b/TalerWallet1/Views/Transactions/TransactionDetailView.swift
@@ -25,11 +25,13 @@ struct TransactionDetailView: View {
     private let symLog = SymLogV(0)
     let stack: CallStack
     @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
+//    @AppStorage("moreContrast") var moreContrast: Bool = false
 #if DEBUG
     @AppStorage("developerMode") var developerMode: Bool = true
 #else
     @AppStorage("developerMode") var developerMode: Bool = false
 #endif
+    @Environment(\.colorSchemeContrast) private var colorSchemeContrast
 
     let transactionId: String
     let reloadAction: ((_ transactionId: String) async throws -> Transaction)
@@ -47,14 +49,9 @@ struct TransactionDetailView: View {
 
     func accessibilityDate(_ date: Date?) -> String? {
         if let date {
-            let dateString = DateFormatter.localizedString(from: date,
-                                                      dateStyle: .short,
-                                                      timeStyle: .none)
-            let hourComponents = Calendar.current.dateComponents([.hour, 
.minute], from: date)
-            if let timeString = DateComponentsFormatter.localizedString(from: 
hourComponents, unitsStyle: .spellOut) {
-                return dateString + ", " + timeString
-            }
-            return dateString
+            let formatted = date.formatted(date: .long, time: .shortened)
+//            print(formatted)
+            return formatted
         }
         return nil
     }
@@ -68,8 +65,7 @@ struct TransactionDetailView: View {
         let pending = transaction.isPending
         let locale = TalerDater.shared.locale
         let (dateString, date) = TalerDater.dateString(from: common.timestamp)
-        let accessibilityDate = accessibilityDate(date) ??
-                                    dateString
+        let accessibilityDate = accessibilityDate(date) ?? dateString
         let navTitle2 = transaction.localizedType
         Group {
             List {
@@ -86,7 +82,8 @@ struct TransactionDetailView: View {
                 Text(dateString)
                     .accessibilityFont(.body)
                     .accessibilityLabel(accessibilityDate)
-                    .foregroundColor(.secondary)
+                    .foregroundColor(colorSchemeContrast == .increased ? 
.primary : .secondary)
+//                    .foregroundColor(moreContrast ? .primary : .secondary)
                     .listRowSeparator(.hidden)
                 HStack {
                     Text(verbatim: "|")   // only reason for this 
leading-aligned text is to get a nice full length listRowSeparator
@@ -121,20 +118,21 @@ struct TransactionDetailView: View {
                 }
         }.onNotification(.TransactionStateTransition) { notification in
             if let transition = notification.userInfo?[TRANSACTIONTRANSITION] 
as? TransactionTransition {
-                if transition.transactionId == common.transactionId {
+                if transition.transactionId == common.transactionId {       // 
is the transition for THIS transaction?
                     let newMajor = transition.newTxState.major
                     let newMinor = transition.newTxState.minor
                     if let doneAction {
                         if newMajor == .done {
                             symLog.log("newTxState.major == done  => dismiss 
sheet")
+// TODO:                           logger.info("newTxState.major == done  => 
dismiss sheet")
                             doneAction()        // if this view is in a sheet 
this action will dissmiss it
                         } else if newMajor == .expired {
                             symLog.log("newTxState.major == expired  => 
dismiss sheet")
+// TODO:                           logger.info("newTxState.major == expired  
=> dismiss sheet")
                             doneAction()        // if this view is in a sheet 
this action will dissmiss it
                         } else if newMajor == .pending {
                             if let newMinor {
                                 if newMinor == .exchangeWaitReserve { // user 
did confirm on bank website
-//                                    symLog.log("newTxState.minor == 
exchangeWaitReserve  => change Buttons")
                                     symLog.log("newTxState.minor == 
exchangeWaitReserve => dismiss sheet")
                                     doneAction()        // if this view is in 
a sheet this action will dissmiss it
                                 } else if newMinor == .withdrawCoins { // 
coin-withdrawal has started
@@ -158,8 +156,8 @@ struct TransactionDetailView: View {
                           symLog.log(error.localizedDescription)
                     }}}
                 }
-            } else {
-                // Yikes - should never happen
+            } else { // Yikes - should never happen
+// TODO:                logger.warning("Can't get notification.userInfo as 
TransactionTransition")
                 symLog.log(notification.userInfo as Any)
             }
         }
@@ -196,7 +194,8 @@ struct TransactionDetailView: View {
             Group {
                 switch transaction {
                     case .dummy(_):
-                        Text("")
+                        let title = ""
+                        Text(title)
                             .accessibilityFont(.body)
                     case .withdrawal(let withdrawalTransaction):
                         let details = withdrawalTransaction.details
@@ -204,7 +203,7 @@ struct TransactionDetailView: View {
                             let withdrawalDetails = details.withdrawalDetails
                             switch withdrawalDetails.type {
                                 case .manual:               // "Make a wire 
transfer of \(amount) to"
-                                    ManualDetails(common: common, details: 
withdrawalDetails)
+                                    ManualDetailsV(common: common, details: 
withdrawalDetails)
                                     
                                 case .bankIntegrated:       // "Confirm with 
bank"
                                     let confirmed = 
withdrawalDetails.confirmed ?? false
@@ -270,8 +269,9 @@ struct TransactionDetailView: View {
                                     .padding(.top)
                             }
                         }
-                        ThreeAmountsSheet(common: common, topAbbrev: 
transaction.localizedType,
-                                        topTitle: transaction.localizedType,
+                        let colon = ":"
+                        ThreeAmountsSheet(common: common, topAbbrev: 
transaction.localizedType + colon,
+                                        topTitle: transaction.localizedType + 
colon,
                                          baseURL: details.exchangeBaseUrl, 
large: false)
                 } // switch
             } // Group
diff --git a/TalerWallet1/Views/Transactions/TransactionRowView.swift 
b/TalerWallet1/Views/Transactions/TransactionRowView.swift
index fc28f09..f51e1c6 100644
--- a/TalerWallet1/Views/Transactions/TransactionRowView.swift
+++ b/TalerWallet1/Views/Transactions/TransactionRowView.swift
@@ -79,7 +79,7 @@ struct TransactionRowView: View {
         let incoming = common.incoming()
         let foreColor = pending ? WalletColors().pendingColor(incoming)
                       : done ? WalletColors().transactionColor(incoming)
-                             : WalletColors().uncompletedColor
+                             : WalletColors().incompleteColor
 
         SingleAxisGeometryReader { width in
             Group {
@@ -96,6 +96,8 @@ struct TransactionRowView: View {
                     TransactionRowContentV(centerTop: 
transaction.localizedType,
                                            centerBottom: dateString, 
isHorizontal: true, incoming: incoming, foreColor: foreColor)
                 }
+                    .accessibilityElement(children: .combine)
+                    .accessibilityHint("Will go to detail view.")
             }
         }
     }
diff --git a/TalerWallet1/Views/Transactions/TransactionsListView.swift 
b/TalerWallet1/Views/Transactions/TransactionsListView.swift
index 6dc1a4b..7160969 100644
--- a/TalerWallet1/Views/Transactions/TransactionsListView.swift
+++ b/TalerWallet1/Views/Transactions/TransactionsListView.swift
@@ -62,6 +62,7 @@ struct TransactionsListView: View {
             }
         } // ScrollView
         .navigationTitle(navTitle)
+        .accessibilityHint(Text("Transaction list"))
         .task {
             symLog.log(".task ")
             await reloadAllAction(stack.push())
diff --git a/TestFlight/WhatToTest.en-US.txt b/TestFlight/WhatToTest.en-US.txt
index f19988a..4de97d4 100644
--- a/TestFlight/WhatToTest.en-US.txt
+++ b/TestFlight/WhatToTest.en-US.txt
@@ -1,7 +1,17 @@
 
+Version 0.9.3 (24)
+
+• Sound & Haptics ON by default
+• Blue Taler Logo
+- Lots of Accessibility improvements
+- BugFix: P2P Transactions were started twice
+- Incomplete Transactions no longer show "Obtained" or "Paid"
+
+
 Version 0.9.3 (23)
 
 - Fixed layout for Pending + Transactions for dynamic font sizes
+- CurrencyFormatter for Pending + Transactions
 
 
 Version 0.9.3 (22)

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]