gnunet-svn
[Top][All Lists]
Advanced

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

[taler-taler-ios] branch master updated (7d32de8 -> 8b2cfb1)


From: gnunet
Subject: [taler-taler-ios] branch master updated (7d32de8 -> 8b2cfb1)
Date: Tue, 19 Sep 2023 03:44:19 +0200

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 7d32de8  Font Settings
     new 551285d  Haptics
     new 66e81ea  move to HelperViews
     new c39cd35  talerFonts
     new dbf95e6  Font
     new 78bb026  Terms of Service
     new 7a069e5  Black
     new 2c61b55  DebugView static font size
     new 112dfef  Binding+onChange
     new 5c15352  move AgePicker
     new 241f614  ExchangeTosStatus
     new 44ea233  AccessibleFont
     new 43d27dc  Italic
     new 275d69e  Comment
     new 42d0f27  ToSButton
     new 9f7b1e5  Speed up Sidebar
     new f8cbf4d  ScreenSize
     new d948bb6  Bargraph shows the last transactions visually
     new f54e0f8  MainActor for Swift 6
     new cb08027  Sendable for Swift 6
     new 880bc04  Wording: don't use "encrypt"
     new 5360255  test.taler.net now uses KUDOS (instead of TESTKUDOS)
     new 027354f  CallStack
     new 75df49f  logging
     new f1ee0e8  more CallStack debugging
     new ec15415  simplify
     new dc8b888  fix warning
     new e46e434  simplify log
     new 8b2cfb1  !!! Temporarily add back old cases to ExchangeTosStatus to be 
able to run with older wallet-core version !!!

The 28 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:
 GNU_Taler Info.plist                               |   2 +
 TalerWallet.xcodeproj/project.pbxproj              |  52 +++-
 TalerWallet1/Backend/Transaction.swift             |  24 +-
 TalerWallet1/Backend/WalletCore.swift              |  14 +-
 TalerWallet1/Controllers/Controller.swift          |   3 +
 TalerWallet1/Controllers/DebugViewC.swift          |   2 +-
 TalerWallet1/Controllers/PublicConstants.swift     |   3 +-
 TalerWallet1/Controllers/TalerWallet1App.swift     |   2 +-
 TalerWallet1/Fonts/Nunito/Nunito-Black.ttf         | Bin 0 -> 131568 bytes
 TalerWallet1/Fonts/Nunito/Nunito-BlackItalic.ttf   | Bin 0 -> 134488 bytes
 ...boardResponder.swift => Binding+onChange.swift} |  46 +--
 TalerWallet1/Helper/CallStack.swift                |  89 ++++++
 TalerWallet1/Helper/Controller+playSound.swift     |   7 +-
 TalerWallet1/Helper/Font+Taler.swift               | 317 +++++++++++++++------
 TalerWallet1/Helper/KeyboardResponder.swift        |   1 +
 TalerWallet1/Helper/UIScreen+screenSize.swift      |  11 +
 TalerWallet1/Helper/View+Notification.swift        |   2 +-
 TalerWallet1/Helper/View+dismissTop.swift          |   2 +-
 TalerWallet1/Helper/View+flippedDirection.swift    |  21 ++
 TalerWallet1/Model/Model+Balances.swift            |   6 +-
 TalerWallet1/Model/Model+Exchange.swift            |  26 +-
 TalerWallet1/Model/Model+Transactions.swift        |   6 +-
 TalerWallet1/Model/Model+Withdraw.swift            |   3 +
 TalerWallet1/Model/WalletModel.swift               |   2 +-
 TalerWallet1/Views/Balances/BalanceRowView.swift   |  17 +-
 TalerWallet1/Views/Balances/BalancesListView.swift |  33 ++-
 .../Views/Balances/BalancesSectionView.swift       | 100 ++++---
 TalerWallet1/Views/Balances/PendingRowView.swift   |  14 +-
 .../Views/Balances/UncompletedRowView.swift        |   2 +-
 TalerWallet1/Views/Exchange/ExchangeListView.swift |  18 +-
 .../Views/Exchange/ExchangeSectionView.swift       |  33 ++-
 TalerWallet1/Views/Exchange/ManualWithdraw.swift   |  40 ++-
 .../Views/Exchange/ManualWithdrawDone.swift        |  35 +--
 TalerWallet1/Views/Exchange/QuiteSomeCoins.swift   |  10 +-
 .../{Helper => Views/HelperViews}/AgePicker.swift  |   3 +-
 TalerWallet1/Views/HelperViews/AmountView.swift    |   6 +-
 TalerWallet1/Views/HelperViews/BarGraph.swift      |  87 ++++++
 TalerWallet1/Views/HelperViews/Buttons.swift       |  29 +-
 TalerWallet1/Views/HelperViews/CopyShare.swift     |   3 +
 TalerWallet1/Views/HelperViews/CurrencyField.swift |   6 +-
 .../Views/HelperViews/CurrencyInputView.swift      |   4 +-
 .../Views/HelperViews/LaunchAnimationView.swift    |   2 +-
 .../Views/HelperViews/QRCodeDetailView.swift       |   5 +-
 .../Views/HelperViews/TextFieldAlert.swift         |   5 +-
 TalerWallet1/Views/HelperViews/ToSButtonView.swift |  35 +++
 .../Views/HelperViews/TransactionButton.swift      |   4 +-
 TalerWallet1/Views/Main/MainView.swift             |  45 ++-
 TalerWallet1/Views/Main/SideBarView.swift          |  20 +-
 TalerWallet1/Views/Main/WalletEmptyView.swift      |   2 +-
 TalerWallet1/Views/Payment/PayTemplateView.swift   |   5 +-
 TalerWallet1/Views/Payment/PaymentView.swift       |   9 +-
 TalerWallet1/Views/Peer2peer/PaymentPurpose.swift  |  21 +-
 TalerWallet1/Views/Peer2peer/RequestPayment.swift  |  14 +-
 TalerWallet1/Views/Peer2peer/SendAmount.swift      |  24 +-
 TalerWallet1/Views/Peer2peer/SendDone.swift        |  31 +-
 TalerWallet1/Views/Peer2peer/SendPurpose.swift     |  27 +-
 .../Views/Settings/Pending/PendingOpView.swift     |  35 +--
 TalerWallet1/Views/Settings/SettingsItem.swift     |  25 +-
 TalerWallet1/Views/Settings/SettingsView.swift     |  30 +-
 .../Views/Sheets/P2P_Sheets/P2pAcceptDone.swift    |  26 +-
 .../Views/Sheets/P2P_Sheets/P2pPayURIView.swift    |   8 +-
 .../Sheets/P2P_Sheets/P2pReceiveURIView.swift      |  22 +-
 TalerWallet1/Views/Sheets/QRSheet.swift            |   5 +-
 TalerWallet1/Views/Sheets/ShareSheet.swift         |   2 +-
 TalerWallet1/Views/Sheets/Sheet.swift              |   9 +-
 TalerWallet1/Views/Sheets/URLSheet.swift           |  15 +-
 .../Views/Transactions/ManualDetails.swift         |  91 +++---
 TalerWallet1/Views/Transactions/ThreeAmounts.swift |   4 +-
 .../Views/Transactions/TransactionDetailView.swift |  23 +-
 .../Views/Transactions/TransactionRowView.swift    |  10 +-
 .../Views/Transactions/TransactionsEmptyView.swift |   4 +-
 .../Views/Transactions/TransactionsListView.swift  |  22 +-
 .../WithdrawAcceptDone.swift                       |  27 +-
 .../WithdrawAcceptView.swift                       |   2 +-
 .../WithdrawProgressView.swift                     |   2 +-
 .../WithdrawBankIntegrated/WithdrawTOSView.swift   |  13 +-
 .../WithdrawBankIntegrated/WithdrawURIView.swift   |  21 +-
 Taler_Wallet Info.plist                            |   2 +
 taler-swift/Sources/taler-swift/Amount.swift       |  12 +-
 taler-swift/Sources/taler-swift/Time.swift         |   2 +-
 80 files changed, 1157 insertions(+), 585 deletions(-)
 create mode 100644 TalerWallet1/Fonts/Nunito/Nunito-Black.ttf
 create mode 100644 TalerWallet1/Fonts/Nunito/Nunito-BlackItalic.ttf
 copy TalerWallet1/Helper/{KeyboardResponder.swift => Binding+onChange.swift} 
(53%)
 create mode 100644 TalerWallet1/Helper/CallStack.swift
 create mode 100644 TalerWallet1/Helper/UIScreen+screenSize.swift
 create mode 100644 TalerWallet1/Helper/View+flippedDirection.swift
 rename TalerWallet1/{Helper => Views/HelperViews}/AgePicker.swift (94%)
 create mode 100644 TalerWallet1/Views/HelperViews/BarGraph.swift
 create mode 100644 TalerWallet1/Views/HelperViews/ToSButtonView.swift

diff --git a/GNU_Taler Info.plist b/GNU_Taler Info.plist
index 5c6173c..b6dac8f 100644
--- a/GNU_Taler Info.plist      
+++ b/GNU_Taler Info.plist      
@@ -32,6 +32,8 @@
                <string>Atkinson-Hyperlegible-Italic-102.otf</string>
                <string>Nunito-Regular.ttf</string>
                <string>Nunito-Bold.ttf</string>
+               <string>Nunito-Black.ttf</string>
+               <string>Nunito-BlackItalic.ttf</string>
                <string>Nunito-BoldItalic.ttf</string>
                <string>Nunito-Italic.ttf</string>
        </array>
diff --git a/TalerWallet.xcodeproj/project.pbxproj 
b/TalerWallet.xcodeproj/project.pbxproj
index aa9e2a0..4d6133d 100644
--- a/TalerWallet.xcodeproj/project.pbxproj
+++ b/TalerWallet.xcodeproj/project.pbxproj
@@ -130,6 +130,8 @@
                4E3EAEA32AA12582009F1BE8 /* Nunito-Italic.ttf in Resources */ = 
{isa = PBXBuildFile; fileRef = 4E3EAEA02AA12582009F1BE8 /* Nunito-Italic.ttf 
*/; };
                4E3EAEA42AA12582009F1BE8 /* Nunito-BoldItalic.ttf in Resources 
*/ = {isa = PBXBuildFile; fileRef = 4E3EAEA12AA12582009F1BE8 /* 
Nunito-BoldItalic.ttf */; };
                4E3EAEA52AA12582009F1BE8 /* Nunito-BoldItalic.ttf in Resources 
*/ = {isa = PBXBuildFile; fileRef = 4E3EAEA12AA12582009F1BE8 /* 
Nunito-BoldItalic.ttf */; };
+               4E3EAEA82AA70157009F1BE8 /* Binding+onChange.swift in Sources 
*/ = {isa = PBXBuildFile; fileRef = 4E3EAEA72AA70157009F1BE8 /* 
Binding+onChange.swift */; };
+               4E3EAEA92AA70157009F1BE8 /* Binding+onChange.swift in Sources 
*/ = {isa = PBXBuildFile; fileRef = 4E3EAEA72AA70157009F1BE8 /* 
Binding+onChange.swift */; };
                4E40E0BE29F25ABB00B85369 /* SendAmount.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4E40E0BD29F25ABB00B85369 /* SendAmount.swift */; 
};
                4E50B3502A1BEE8000F9F01C /* ManualWithdraw.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 4E50B34F2A1BEE8000F9F01C /* 
ManualWithdraw.swift */; };
                4E53A33729F50B7B00830EC2 /* CurrencyField.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4E53A33629F50B7B00830EC2 /* CurrencyField.swift 
*/; };
@@ -137,6 +139,16 @@
                4E578E942A4822D500F21F1C /* P2pPayURIView.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4E578E932A4822D500F21F1C /* P2pPayURIView.swift 
*/; };
                4E5A88F52A38A4FD00072618 /* QRCodeDetailView.swift in Sources 
*/ = {isa = PBXBuildFile; fileRef = 4E5A88F42A38A4FD00072618 /* 
QRCodeDetailView.swift */; };
                4E5A88F72A3B9E5B00072618 /* WithdrawAcceptDone.swift in Sources 
*/ = {isa = PBXBuildFile; fileRef = 4E5A88F62A3B9E5B00072618 /* 
WithdrawAcceptDone.swift */; };
+               4E605D902AA8B407002FB9A7 /* Nunito-Black.ttf in Resources */ = 
{isa = PBXBuildFile; fileRef = 4E605D8E2AA8B407002FB9A7 /* Nunito-Black.ttf */; 
};
+               4E605D912AA8B407002FB9A7 /* Nunito-Black.ttf in Resources */ = 
{isa = PBXBuildFile; fileRef = 4E605D8E2AA8B407002FB9A7 /* Nunito-Black.ttf */; 
};
+               4E605D922AA8B407002FB9A7 /* Nunito-BlackItalic.ttf in Resources 
*/ = {isa = PBXBuildFile; fileRef = 4E605D8F2AA8B407002FB9A7 /* 
Nunito-BlackItalic.ttf */; };
+               4E605D932AA8B407002FB9A7 /* Nunito-BlackItalic.ttf in Resources 
*/ = {isa = PBXBuildFile; fileRef = 4E605D8F2AA8B407002FB9A7 /* 
Nunito-BlackItalic.ttf */; };
+               4E605DAF2AADDD13002FB9A7 /* UIScreen+screenSize.swift in 
Sources */ = {isa = PBXBuildFile; fileRef = 4E605DAE2AADDD13002FB9A7 /* 
UIScreen+screenSize.swift */; };
+               4E605DB02AADDD13002FB9A7 /* UIScreen+screenSize.swift in 
Sources */ = {isa = PBXBuildFile; fileRef = 4E605DAE2AADDD13002FB9A7 /* 
UIScreen+screenSize.swift */; };
+               4E605DB72AB05E48002FB9A7 /* View+flippedDirection.swift in 
Sources */ = {isa = PBXBuildFile; fileRef = 4E605DB62AB05E48002FB9A7 /* 
View+flippedDirection.swift */; };
+               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 
*/; };
                4E6EDD872A363D8D0031D520 /* ListStyle.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4E6EDD862A363D8D0031D520 /* ListStyle.swift */; 
};
                4E753A062A0952F8002D9328 /* DebugViewC.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4E753A052A0952F7002D9328 /* DebugViewC.swift */; 
};
@@ -217,11 +229,15 @@
                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 
*/; };
+               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 */; };
                4EEC157629F8ECBF00D46A03 /* CodeScanner in Frameworks */ = {isa 
= PBXBuildFile; productRef = 4EEC157529F8ECBF00D46A03 /* CodeScanner */; };
                4EEC157829F9032900D46A03 /* Sheet.swift in Sources */ = {isa = 
PBXBuildFile; fileRef = 4EEC157729F9032900D46A03 /* Sheet.swift */; };
                4EEC157A29F9427F00D46A03 /* QRSheet.swift in Sources */ = {isa 
= PBXBuildFile; fileRef = 4EEC157929F9427F00D46A03 /* QRSheet.swift */; };
                4EF840A72A0B85F400EE0D47 /* CopyShare.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4EF840A62A0B85F400EE0D47 /* CopyShare.swift */; 
};
+               4EFA39602AA7946B00742548 /* ToSButtonView.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4EFA395F2AA7946B00742548 /* ToSButtonView.swift 
*/; };
+               4EFA39612AA7946B00742548 /* ToSButtonView.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 4EFA395F2AA7946B00742548 /* ToSButtonView.swift 
*/; };
                ABC13AA32859962800D23185 /* taler-swift in Frameworks */ = {isa 
= PBXBuildFile; productRef = ABC13AA22859962800D23185 /* taler-swift */; };
                ABE97B1D286D82BF00580772 /* AnyCodable in Frameworks */ = {isa 
= PBXBuildFile; productRef = ABE97B1C286D82BF00580772 /* AnyCodable */; };
 /* End PBXBuildFile section */
@@ -283,6 +299,7 @@
                4E3EAE9B2AA12467009F1BE8 /* Nunito-Bold.ttf */ = {isa = 
PBXFileReference; lastKnownFileType = file; path = "Nunito-Bold.ttf"; 
sourceTree = "<group>"; };
                4E3EAEA02AA12582009F1BE8 /* Nunito-Italic.ttf */ = {isa = 
PBXFileReference; lastKnownFileType = file; path = "Nunito-Italic.ttf"; 
sourceTree = "<group>"; };
                4E3EAEA12AA12582009F1BE8 /* Nunito-BoldItalic.ttf */ = {isa = 
PBXFileReference; lastKnownFileType = file; path = "Nunito-BoldItalic.ttf"; 
sourceTree = "<group>"; };
+               4E3EAEA72AA70157009F1BE8 /* Binding+onChange.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= "Binding+onChange.swift"; sourceTree = "<group>"; };
                4E40E0BD29F25ABB00B85369 /* SendAmount.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= SendAmount.swift; sourceTree = "<group>"; };
                4E50B34F2A1BEE8000F9F01C /* ManualWithdraw.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= ManualWithdraw.swift; sourceTree = "<group>"; };
                4E53A33629F50B7B00830EC2 /* CurrencyField.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= CurrencyField.swift; sourceTree = "<group>"; };
@@ -290,6 +307,11 @@
                4E578E932A4822D500F21F1C /* P2pPayURIView.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
P2pPayURIView.swift; sourceTree = "<group>"; };
                4E5A88F42A38A4FD00072618 /* QRCodeDetailView.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= QRCodeDetailView.swift; sourceTree = "<group>"; };
                4E5A88F62A3B9E5B00072618 /* WithdrawAcceptDone.swift */ = {isa 
= PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; 
path = WithdrawAcceptDone.swift; sourceTree = "<group>"; };
+               4E605D8E2AA8B407002FB9A7 /* Nunito-Black.ttf */ = {isa = 
PBXFileReference; lastKnownFileType = file; path = "Nunito-Black.ttf"; 
sourceTree = "<group>"; };
+               4E605D8F2AA8B407002FB9A7 /* Nunito-BlackItalic.ttf */ = {isa = 
PBXFileReference; lastKnownFileType = file; path = "Nunito-BlackItalic.ttf"; 
sourceTree = "<group>"; };
+               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>"; };
                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>"; };
@@ -372,10 +394,12 @@
                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>"; };
+               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>"; };
                4EEC157929F9427F00D46A03 /* QRSheet.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= QRSheet.swift; sourceTree = "<group>"; };
                4EF840A62A0B85F400EE0D47 /* CopyShare.swift */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path 
= CopyShare.swift; sourceTree = "<group>"; };
+               4EFA395F2AA7946B00742548 /* ToSButtonView.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
ToSButtonView.swift; sourceTree = "<group>"; };
                AB710490285995B6008B04F0 /* taler-swift */ = {isa = 
PBXFileReference; lastKnownFileType = text; path = "taler-swift"; sourceTree = 
SOURCE_ROOT; };
                D14AFD1D24D232B300C51073 /* Taler_Wallet.app */ = {isa = 
PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; 
path = Taler_Wallet.app; sourceTree = BUILT_PRODUCTS_DIR; };
                D14AFD3324D232B500C51073 /* TalerTests.xctest */ = {isa = 
PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path 
= TalerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -450,6 +474,8 @@
                                4E3EAE9B2AA12467009F1BE8 /* Nunito-Bold.ttf */,
                                4E3EAEA12AA12582009F1BE8 /* 
Nunito-BoldItalic.ttf */,
                                4E3EAEA02AA12582009F1BE8 /* Nunito-Italic.ttf 
*/,
+                               4E605D8E2AA8B407002FB9A7 /* Nunito-Black.ttf */,
+                               4E605D8F2AA8B407002FB9A7 /* 
Nunito-BlackItalic.ttf */,
                        );
                        path = Nunito;
                        sourceTree = "<group>";
@@ -531,17 +557,20 @@
                4EB095052989CB7C0043A8A1 /* Helper */ = {
                        isa = PBXGroup;
                        children = (
-                               4E97968F2A3765ED006F73BC /* AgePicker.swift */,
                                4E363CBD2A23CB2100D7E98C /* 
AnyTransition+backslide.swift */,
+                               4EDBDCD82AB787CB00925C02 /* CallStack.swift */,
                                4E16E12229F3BB99008B9C86 /* 
CurrencyFormatter.swift */,
                                4EAD117529F672FA008EDD0B /* 
KeyboardResponder.swift */,
                                4E363CC12A2621C200D7E98C /* 
LocalizedAlertError.swift */,
                                4E578E912A481D8600F21F1C /* 
Controller+playSound.swift */,
                                4EB095062989CB7C0043A8A1 /* TalerDater.swift */,
                                4EB095072989CB7C0043A8A1 /* TalerStrings.swift 
*/,
+                               4E3EAEA72AA70157009F1BE8 /* 
Binding+onChange.swift */,
                                4E3EAE8B2AA0933C009F1BE8 /* Font+Taler.swift */,
                                4EB095082989CB7C0043A8A1 /* 
View+dismissTop.swift */,
+                               4E605DB62AB05E48002FB9A7 /* 
View+flippedDirection.swift */,
                                4E3B4BC62A429F2A00CC88B8 /* 
View+Notification.swift */,
+                               4E605DAE2AADDD13002FB9A7 /* 
UIScreen+screenSize.swift */,
                                4E363CBB2A237E0900D7E98C /* URL+id+iban.swift 
*/,
                                4E9320422A14F6EA00A87B0E /* WalletColors.swift 
*/,
                                4E8E25322A1CD39700A27BFA /* 
EqualIconWidthDomain.swift */,
@@ -684,6 +713,8 @@
                4EB095462989CBFE0043A8A1 /* HelperViews */ = {
                        isa = PBXGroup;
                        children = (
+                               4E97968F2A3765ED006F73BC /* AgePicker.swift */,
+                               4E605DB92AB05FB6002FB9A7 /* BarGraph.swift */,
                                4EB095472989CBFE0043A8A1 /* Buttons.swift */,
                                4EF840A62A0B85F400EE0D47 /* CopyShare.swift */,
                                4ECB62812A0BB01D004ABBB7 /* SelectDays.swift */,
@@ -697,6 +728,7 @@
                                4EB095492989CBFE0043A8A1 /* AmountView.swift */,
                                4EB0954A2989CBFE0043A8A1 /* LoadingView.swift 
*/,
                                4EB095432989CBFE0043A8A1 /* 
LaunchAnimationView.swift */,
+                               4EFA395F2AA7946B00742548 /* ToSButtonView.swift 
*/,
                        );
                        path = HelperViews;
                        sourceTree = "<group>";
@@ -928,8 +960,10 @@
                                4E3EAE812A990778009F1BE8 /* 
Atkinson-Hyperlegible-BoldItalic-102.otf in Resources */,
                                4E3EAE832A990778009F1BE8 /* 
Atkinson-Hyperlegible-Italic-102.otf in Resources */,
                                4E3EAE9C2AA12467009F1BE8 /* Nunito-Regular.ttf 
in Resources */,
+                               4E605D922AA8B407002FB9A7 /* 
Nunito-BlackItalic.ttf in Resources */,
                                4E3EAE9E2AA12467009F1BE8 /* Nunito-Bold.ttf in 
Resources */,
                                4E3EAEA42AA12582009F1BE8 /* 
Nunito-BoldItalic.ttf in Resources */,
+                               4E605D902AA8B407002FB9A7 /* Nunito-Black.ttf in 
Resources */,
                                4E3EAEA22AA12582009F1BE8 /* Nunito-Italic.ttf 
in Resources */,
                                4E3EAE822A990778009F1BE8 /* 
payment_received.m4a in Resources */,
                                4E3EAE852A990778009F1BE8 /* payment_sent.m4a in 
Resources */,
@@ -947,8 +981,10 @@
                                4E8C17232A6509BB005B2392 /* 
Atkinson-Hyperlegible-BoldItalic-102.otf in Resources */,
                                4E8C17212A6509BB005B2392 /* 
Atkinson-Hyperlegible-Italic-102.otf in Resources */,
                                4E3EAE9D2AA12467009F1BE8 /* Nunito-Regular.ttf 
in Resources */,
+                               4E605D932AA8B407002FB9A7 /* 
Nunito-BlackItalic.ttf in Resources */,
                                4E3EAE9F2AA12467009F1BE8 /* Nunito-Bold.ttf in 
Resources */,
                                4E3EAEA52AA12582009F1BE8 /* 
Nunito-BoldItalic.ttf in Resources */,
+                               4E605D912AA8B407002FB9A7 /* Nunito-Black.ttf in 
Resources */,
                                4E3EAEA32AA12582009F1BE8 /* Nunito-Italic.ttf 
in Resources */,
                                4E2254972A822B8100E41D29 /* 
payment_received.m4a in Resources */,
                                4E2254982A822B8100E41D29 /* payment_sent.m4a in 
Resources */,
@@ -986,6 +1022,7 @@
                                4E3EAE242A990778009F1BE8 /* 
QRGeneratorView.swift in Sources */,
                                4E3EAE252A990778009F1BE8 /* 
WithdrawAcceptDone.swift in Sources */,
                                4E3EAE262A990778009F1BE8 /* Transaction.swift 
in Sources */,
+                               4E605DB72AB05E48002FB9A7 /* 
View+flippedDirection.swift in Sources */,
                                4E3EAE272A990778009F1BE8 /* WalletColors.swift 
in Sources */,
                                4E3EAE282A990778009F1BE8 /* 
BalancesListView.swift in Sources */,
                                4E3EAE292A990778009F1BE8 /* 
WalletBackendError.swift in Sources */,
@@ -997,6 +1034,7 @@
                                4E3EAE2E2A990778009F1BE8 /* 
QRCodeDetailView.swift in Sources */,
                                4E3EAE2F2A990778009F1BE8 /* 
TransactionsEmptyView.swift in Sources */,
                                4E3EAE302A990778009F1BE8 /* 
UncompletedRowView.swift in Sources */,
+                               4E605DAF2AADDD13002FB9A7 /* 
UIScreen+screenSize.swift in Sources */,
                                4E3EAE312A990778009F1BE8 /* SendAmount.swift in 
Sources */,
                                4E3EAE332A990778009F1BE8 /* 
EqualIconWidthDomain.swift in Sources */,
                                4E3EAE342A990778009F1BE8 /* 
SuperScriptDigits.swift in Sources */,
@@ -1024,8 +1062,10 @@
                                4E3EAE4A2A990778009F1BE8 /* 
PaymentPurpose.swift in Sources */,
                                4E3EAE4B2A990778009F1BE8 /* ShareSheet.swift in 
Sources */,
                                4E3EAE4C2A990778009F1BE8 /* AmountView.swift in 
Sources */,
+                               4E605DBA2AB05FB6002FB9A7 /* BarGraph.swift in 
Sources */,
                                4E3EAE4D2A990778009F1BE8 /* P2pAcceptDone.swift 
in Sources */,
                                4E3EAE4E2A990778009F1BE8 /* 
AnyTransition+backslide.swift in Sources */,
+                               4EFA39602AA7946B00742548 /* ToSButtonView.swift 
in Sources */,
                                4E3EAE4F2A990778009F1BE8 /* 
BalanceRowButtons.swift in Sources */,
                                4E3EAE502A990778009F1BE8 /* 
Model+Transactions.swift in Sources */,
                                4E3EAE512A990778009F1BE8 /* 
Controller+playSound.swift in Sources */,
@@ -1061,9 +1101,11 @@
                                4E3EAE6F2A990778009F1BE8 /* TalerStrings.swift 
in Sources */,
                                4E3EAE702A990778009F1BE8 /* 
CurrencyInputView.swift in Sources */,
                                4E3EAE712A990778009F1BE8 /* URL+id+iban.swift 
in Sources */,
+                               4EDBDCD92AB787CB00925C02 /* CallStack.swift in 
Sources */,
                                4E3EAE722A990778009F1BE8 /* 
RequestPayment.swift in Sources */,
                                4E3EAE732A990778009F1BE8 /* SettingsItem.swift 
in Sources */,
                                4E3EAE742A990778009F1BE8 /* 
BalanceRowView.swift in Sources */,
+                               4E3EAEA82AA70157009F1BE8 /* 
Binding+onChange.swift in Sources */,
                                4E3EAE752A990778009F1BE8 /* DebugViewC.swift in 
Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
@@ -1082,6 +1124,7 @@
                                4EEC157329F8242800D46A03 /* 
QRGeneratorView.swift in Sources */,
                                4E5A88F72A3B9E5B00072618 /* 
WithdrawAcceptDone.swift in Sources */,
                                4EB095222989CBCB0043A8A1 /* Transaction.swift 
in Sources */,
+                               4E605DB82AB05E48002FB9A7 /* 
View+flippedDirection.swift in Sources */,
                                4E9320432A14F6EA00A87B0E /* WalletColors.swift 
in Sources */,
                                4EB0955D2989CBFE0043A8A1 /* 
BalancesListView.swift in Sources */,
                                4EB095212989CBCB0043A8A1 /* 
WalletBackendError.swift in Sources */,
@@ -1093,6 +1136,7 @@
                                4E5A88F52A38A4FD00072618 /* 
QRCodeDetailView.swift in Sources */,
                                4E87C8732A31CB7F001C6406 /* 
TransactionsEmptyView.swift in Sources */,
                                4E87C8752A34B411001C6406 /* 
UncompletedRowView.swift in Sources */,
+                               4E605DB02AADDD13002FB9A7 /* 
UIScreen+screenSize.swift in Sources */,
                                4E40E0BE29F25ABB00B85369 /* SendAmount.swift in 
Sources */,
                                4E8E25332A1CD39700A27BFA /* 
EqualIconWidthDomain.swift in Sources */,
                                4EBA563F2A7FD9390084948B /* 
SuperScriptDigits.swift in Sources */,
@@ -1120,8 +1164,10 @@
                                4E9320472A164BC700A87B0E /* 
PaymentPurpose.swift in Sources */,
                                4E753A082A0B6A5F002D9328 /* ShareSheet.swift in 
Sources */,
                                4EB0956C2989CBFE0043A8A1 /* AmountView.swift in 
Sources */,
+                               4E605DBB2AB05FB6002FB9A7 /* BarGraph.swift in 
Sources */,
                                4E3B4BC32A42252300CC88B8 /* P2pAcceptDone.swift 
in Sources */,
                                4E363CBE2A23CB2100D7E98C /* 
AnyTransition+backslide.swift in Sources */,
+                               4EFA39612AA7946B00742548 /* ToSButtonView.swift 
in Sources */,
                                4EB065442A4CD1A80039B91D /* 
BalanceRowButtons.swift in Sources */,
                                4EB095592989CBFE0043A8A1 /* 
Model+Transactions.swift in Sources */,
                                4E578E922A481D8600F21F1C /* 
Controller+playSound.swift in Sources */,
@@ -1157,9 +1203,11 @@
                                4EB0950A2989CB7C0043A8A1 /* TalerStrings.swift 
in Sources */,
                                4EA551252A2C923600FEC9A8 /* 
CurrencyInputView.swift in Sources */,
                                4E363CBC2A237E0900D7E98C /* URL+id+iban.swift 
in Sources */,
+                               4EDBDCDA2AB787CB00925C02 /* CallStack.swift in 
Sources */,
                                4E9320452A1645B600A87B0E /* 
RequestPayment.swift in Sources */,
                                4EB095502989CBFE0043A8A1 /* SettingsItem.swift 
in Sources */,
                                4EB0955C2989CBFE0043A8A1 /* 
BalanceRowView.swift in Sources */,
+                               4E3EAEA92AA70157009F1BE8 /* 
Binding+onChange.swift in Sources */,
                                4E753A062A0952F8002D9328 /* DebugViewC.swift in 
Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
@@ -1334,6 +1382,7 @@
                                SDKROOT = iphoneos;
                                SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
                                SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+                               SWIFT_STRICT_CONCURRENCY = complete;
                                SWIFT_VERSION = 5.0;
                        };
                        name = Debug;
@@ -1388,6 +1437,7 @@
                                SDKROOT = iphoneos;
                                SWIFT_COMPILATION_MODE = wholemodule;
                                SWIFT_OPTIMIZATION_LEVEL = "-O";
+                               SWIFT_STRICT_CONCURRENCY = complete;
                                SWIFT_VERSION = 5.0;
                                VALIDATE_PRODUCT = YES;
                        };
diff --git a/TalerWallet1/Backend/Transaction.swift 
b/TalerWallet1/Backend/Transaction.swift
index 7f2aac5..823e1d7 100644
--- a/TalerWallet1/Backend/Transaction.swift
+++ b/TalerWallet1/Backend/Transaction.swift
@@ -142,7 +142,7 @@ enum TransactionType: String, Codable {
     var isIncoming   : Bool { isP2pIncoming || isWithdrawal || isRefund || 
isReward }
 }
 
-struct TransactionCommon: Decodable {
+struct TransactionCommon: Decodable, Sendable {
     var type: TransactionType
     var txState: TransactionState
     var amountEffective: Amount
@@ -222,7 +222,7 @@ struct WithdrawalTransactionDetails: Decodable {
     var withdrawalDetails: WithdrawalDetails
 }
 
-struct WithdrawalTransaction {
+struct WithdrawalTransaction : Sendable{
     var common: TransactionCommon
     var details: WithdrawalTransactionDetails
 }
@@ -237,7 +237,7 @@ struct PaymentTransactionDetails: Decodable {
     var info: OrderShortInfo
 }
 
-struct PaymentTransaction {
+struct PaymentTransaction : Sendable{
     var common: TransactionCommon
     var details: PaymentTransactionDetails
 }
@@ -250,7 +250,7 @@ struct RefundTransactionDetails: Decodable {
     var info: OrderShortInfo?       // TODO: is this still here?
 }
 
-struct RefundTransaction {
+struct RefundTransaction : Sendable{
     var common: TransactionCommon
     var details: RefundTransactionDetails
 }
@@ -260,7 +260,7 @@ struct RewardTransactionDetails: Decodable {
     var exchangeBaseUrl: String
 }
 
-struct RewardTransaction {
+struct RewardTransaction : Sendable{
     var common: TransactionCommon
     var details: RewardTransactionDetails
 }
@@ -285,32 +285,32 @@ struct RefreshTransactionDetails: Decodable {
     var refreshOutputAmount: Amount
 }
 
-struct RefreshTransaction {
+struct RefreshTransaction : Sendable{
     var common: TransactionCommon
     var details: RefreshTransactionDetails
 }
 
-struct P2pShortInfo: Codable {
+struct P2pShortInfo: Codable, Sendable {
     var summary: String
     var expiration: Timestamp
 }
 
-struct P2PTransactionDetails: Codable {
+struct P2PTransactionDetails: Codable, Sendable {
     var exchangeBaseUrl: String
     var talerUri: String?       // only if we initiated the transaction
     var info: P2pShortInfo
 }
 
-struct P2PTransaction {
+struct P2PTransaction : Sendable{
     var common: TransactionCommon
     var details: P2PTransactionDetails
 }
 
-struct DummyTransaction {
+struct DummyTransaction : Sendable{
     var common: TransactionCommon
 }
 
-enum Transaction: Decodable, Hashable, Identifiable {
+enum Transaction: Decodable, Hashable, Identifiable, Sendable {
     case dummy (DummyTransaction)
     case withdrawal (WithdrawalTransaction)
     case payment (PaymentTransaction)
@@ -446,7 +446,7 @@ enum Transaction: Decodable, Hashable, Identifiable {
     func detailsToShow() -> Dictionary<String, String> {
         var result: [String:String] = [:]
         switch self {
-            case .dummy(let dummyTransaction):
+            case .dummy(_):  // let dummyTransaction
                 break
             case .withdrawal(let withdrawalTransaction):
                 result[EXCHANGEBASEURL] = 
withdrawalTransaction.details.exchangeBaseUrl
diff --git a/TalerWallet1/Backend/WalletCore.swift 
b/TalerWallet1/Backend/WalletCore.swift
index f2f0460..a3b8dbb 100644
--- a/TalerWallet1/Backend/WalletCore.swift
+++ b/TalerWallet1/Backend/WalletCore.swift
@@ -151,8 +151,7 @@ extension WalletCore {
     private func postNotification(_ aName: NSNotification.Name,
                           object anObject: Any? = nil,
                                  userInfo: [AnyHashable: Any]? = nil) {
-        Task {
-            if let userInfo { symLog.log(userInfo) } else { symLog.log(aName) }
+        Task { // runs on MainActor
             await postNotificationM(aName, object: anObject, userInfo: 
userInfo)
             logger.log("Notification sent: \(aName.rawValue)")
         }
@@ -182,7 +181,7 @@ extension WalletCore {
             logger.log("❗️ \(pendingOp, privacy: .public): \(id, privacy: 
.public)")        // this is a new pendingOp I haven't seen before
         }
     }
-    private func handleStateTransition(_ jsonData: Data) throws {
+    @MainActor private func handleStateTransition(_ jsonData: Data) throws {
         do {
             let decoded = try JSONDecoder().decode(TransactionTransition.self, 
from: jsonData)
             if decoded.newTxState != decoded.oldTxState {
@@ -206,7 +205,7 @@ extension WalletCore {
         }
     }
 
-    private func handleNotification(_ anyCodable: AnyCodable?) throws {
+    @MainActor private func handleNotification(_ anyCodable: AnyCodable?) 
throws {
         guard let anyPayload = anyCodable else { throw 
WalletBackendError.deserializationError }
         do {
             let jsonData = try JSONEncoder().encode(anyPayload)
@@ -214,12 +213,15 @@ extension WalletCore {
 
             switch payload.type {
                 case Notification.Name.TransactionStateTransition.rawValue:
+                    symLog.log(anyPayload)
                     try handleStateTransition(jsonData)
                 case Notification.Name.PendingOperationProcessed.rawValue:
                     try handlePendingProcessed(payload)
                 case Notification.Name.BalanceChange.rawValue:
+                    symLog.log(anyPayload)
                     postNotification(.BalanceChange)
                 case Notification.Name.ExchangeAdded.rawValue:
+                    symLog.log(anyPayload)
                     postNotification(.ExchangeAdded)
                 case Notification.Name.ReserveNotYetFound.rawValue:
                     if let reservePub = payload.reservePub {
@@ -256,7 +258,7 @@ print("\n❗️ WalletCore.swift:226 Notification: ", 
anyPayload, "\n")        /
     }
 
     /// here not only responses, but also notifications from wallet-core will 
be received
-    func handleMessage(message: String) {
+    @MainActor func handleMessage(message: String) {
         do {
             var asyncDelay = 0
             if let delay: Bool = developDelay {   // Settings: 2 seconds delay
@@ -332,7 +334,7 @@ print("\n❗️ WalletCore.swift:226 Notification: ", 
anyPayload, "\n")        /
 // MARK: -  async / await function
 extension WalletCore {
     /// send async requests to wallet-core
-    func sendFormattedRequest<T: WalletBackendFormattedRequest> (request: T) 
async throws -> (T.Response, UInt) {
+    func sendFormattedRequest<T: WalletBackendFormattedRequest> (_ request: T) 
async throws -> (T.Response, UInt) {
         let reqData = WalletBackendRequest(operation: request.operation(),
                                            args: AnyEncodable(request.args()))
         return try await withCheckedThrowingContinuation { continuation in
diff --git a/TalerWallet1/Controllers/Controller.swift 
b/TalerWallet1/Controllers/Controller.swift
index 0dbd42c..35c2c6a 100644
--- a/TalerWallet1/Controllers/Controller.swift
+++ b/TalerWallet1/Controllers/Controller.swift
@@ -7,6 +7,7 @@ import AVFoundation
 import SwiftUI
 import SymLog
 import os.log
+import CoreHaptics
 
 enum BackendState {
     case none
@@ -32,8 +33,10 @@ class Controller: ObservableObject {
     private let symLog = SymLogC()
 
     @Published var backendState: BackendState = .none       // only used for 
launch animation
+    @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("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")
     let player = AVQueuePlayer()
 
diff --git a/TalerWallet1/Controllers/DebugViewC.swift 
b/TalerWallet1/Controllers/DebugViewC.swift
index 89209f9..b1dee53 100644
--- a/TalerWallet1/Controllers/DebugViewC.swift
+++ b/TalerWallet1/Controllers/DebugViewC.swift
@@ -124,8 +124,8 @@ struct DebugViewV: View {
                 Spacer()
             }
             Text(viewIDString)
-                .font(.caption2)
                 .foregroundColor(.red)
+                .font(.system(size: 11))        // no accessibilityFont
                 .monospacedDigit()
             Spacer()
         }
diff --git a/TalerWallet1/Controllers/PublicConstants.swift 
b/TalerWallet1/Controllers/PublicConstants.swift
index 1be1113..e6a807e 100644
--- a/TalerWallet1/Controllers/PublicConstants.swift
+++ b/TalerWallet1/Controllers/PublicConstants.swift
@@ -25,7 +25,8 @@ public let TESTEXCHANGE = HTTPS + "exchange.test.taler.net"
 public let ARS_AGE_EXCHANGE = HTTPS + "exchange-age.taler.ar"
 public let ARS_EXP_EXCHANGE = HTTPS + "exchange-expensive.taler.ar"
 public let DEMOCURRENCY = "KUDOS"
-public let TESTCURRENCY = "TESTKUDOS"
+//public let TESTCURRENCY = "TESTKUDOS"
+public let TESTCURRENCY = "KUDOS"
 //public let LONGCURRENCY = "gold-pressed Latinum"                // 20 
characters, with dash and space
 public let LONGCURRENCY = "GOLDLATINUM"                         // 11 
characters, no dash, no space
 
diff --git a/TalerWallet1/Controllers/TalerWallet1App.swift 
b/TalerWallet1/Controllers/TalerWallet1App.swift
index d46b6d3..4adf008 100644
--- a/TalerWallet1/Controllers/TalerWallet1App.swift
+++ b/TalerWallet1/Controllers/TalerWallet1App.swift
@@ -37,7 +37,7 @@ struct TalerWallet1App: App {
 
     var body: some Scene {
         WindowGroup {
-            MainView(soundPlayed: $soundPlayed)
+            MainView(stack: CallStack("App"), soundPlayed: $soundPlayed)
                 .environmentObject(debugViewC)      // change viewID / sheetID
                 .environmentObject(viewState)       // popToRoot
                 .environmentObject(controller)
diff --git a/TalerWallet1/Fonts/Nunito/Nunito-Black.ttf 
b/TalerWallet1/Fonts/Nunito/Nunito-Black.ttf
new file mode 100644
index 0000000..1081731
Binary files /dev/null and b/TalerWallet1/Fonts/Nunito/Nunito-Black.ttf differ
diff --git a/TalerWallet1/Fonts/Nunito/Nunito-BlackItalic.ttf 
b/TalerWallet1/Fonts/Nunito/Nunito-BlackItalic.ttf
new file mode 100644
index 0000000..e512048
Binary files /dev/null and b/TalerWallet1/Fonts/Nunito/Nunito-BlackItalic.ttf 
differ
diff --git a/TalerWallet1/Helper/KeyboardResponder.swift 
b/TalerWallet1/Helper/Binding+onChange.swift
similarity index 53%
copy from TalerWallet1/Helper/KeyboardResponder.swift
copy to TalerWallet1/Helper/Binding+onChange.swift
index c5d9cde..7bf8a5f 100644
--- a/TalerWallet1/Helper/KeyboardResponder.swift
+++ b/TalerWallet1/Helper/Binding+onChange.swift
@@ -1,5 +1,5 @@
 //  MIT License
-//  Copyright © Nicolai Harbo
+//  Copyright © Paul Hudson
 //
 //  Permission is hereby granted, free of charge, to any person obtaining a 
copy of this software
 //  and associated documentation files (the "Software"), to deal in the 
Software without restriction,
@@ -16,30 +16,30 @@
 //  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
OTHERWISE, ARISING FROM,
 //  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
THE SOFTWARE.
 //
-import Combine
-import UIKit
+import SwiftUI
 
-public final class KeyboardResponder: ObservableObject {
-
-    @Published public var keyboardHeight: CGFloat = 0
-    var showCancellable: AnyCancellable?
-    var hideCancellable: AnyCancellable?
-
-    public init() {
-        showCancellable = NotificationCenter.default.publisher(for: 
UIResponder.keyboardWillShowNotification)
-            .map { notification in
-                
(notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? 
NSValue)?.cgRectValue.height ?? 0.0
+/// Pass the handler directly to the Binding
+extension Binding {
+    func onChange(_ handler: @escaping (Value) -> Void) -> Binding<Value> {
+        Binding (
+            get: { self.wrappedValue },
+            set: { newValue in
+                self.wrappedValue = newValue
+                handler(newValue)
             }
-            .receive(on: DispatchQueue.main)
-            .sink(receiveValue: { height in
-//                print("keyboard height: \(height)")
-                self.keyboardHeight = height
-            })
+        )
+    }
+}
 
-        hideCancellable = NotificationCenter.default.publisher(for: 
UIResponder.keyboardWillHideNotification)
-            .receive(on: DispatchQueue.main)
-            .sink(receiveValue: { _ in
-                self.keyboardHeight = 0
-            })
+#if false
+// use like this:
+struct BindingView: View {
+    @State private var rating = 0.0
+    var body: some View {
+        Slider (value: $rating.onChange(sliderChanged))
+    }
+    func sliderChanged(_ value: Double) {
+        print ("Rating changed to \(value)")
     }
 }
+#endif
diff --git a/TalerWallet1/Helper/CallStack.swift 
b/TalerWallet1/Helper/CallStack.swift
new file mode 100644
index 0000000..fb5d0ec
--- /dev/null
+++ b/TalerWallet1/Helper/CallStack.swift
@@ -0,0 +1,89 @@
+//
+//  Copyright © 2018-2023 Marc Stibane
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a 
copy of this software
+//  and associated documentation files (the "Software"), to deal in the 
Software without restriction,
+//  including without limitation the rights to use, copy, modify, merge, 
publish, distribute,
+//  sublicense, and/or sell copies of the Software, and to permit persons to 
whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in 
all copies or
+//  substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING
+//  BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
PARTICULAR PURPOSE AND
+//  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
LIABLE FOR ANY CLAIM,
+//  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
THE SOFTWARE.
+//
+import Foundation
+
+struct CallStackItem {
+#if DEBUG
+    let file: String
+    let function: String
+#endif
+    let message: String
+}
+
+#if DEBUG
+extension CallStackItem: Identifiable {
+    var id: String { file }
+}
+extension CallStackItem: Equatable {
+    static func == (lhs: CallStackItem, rhs: CallStackItem) -> Bool {
+        lhs.file == rhs.file
+    }
+}
+#endif
+
+
+struct CallStack {
+    private var stack = [CallStackItem]()
+    func peek() -> CallStackItem? { stack.first }
+    func push(item: CallStackItem) -> CallStack {
+        return CallStack(stack: [item] + stack)
+    }
+}
+
+#if DEBUG
+fileprivate func filePath2Name(_ file: String) -> String {
+    let filePath = NSString(string: file)
+    return filePath.lastPathComponent
+}
+#endif
+
+extension CallStack {
+#if DEBUG
+    init(_ message: String = "",
+          funcName: String = #function,
+          filePath: String = #file,
+              line: UInt = #line) {
+        let item = CallStackItem(file: filePath2Name(filePath) + ":\(line)", 
function: funcName, message: message)
+        self.stack = [item]
+    }
+#else
+    init(_ message: String = "") {
+        let item = CallStackItem(message: message)
+        self.storage = [item]
+    }
+#endif
+#if DEBUG
+    public func push(_ message: String = "",
+                      funcName: String = #function,
+                      filePath: String = #file,
+                          line: UInt = #line) -> CallStack {
+        let item = CallStackItem(file: filePath2Name(filePath) + ":\(line)", 
function: funcName, message: message)
+        return push(item: item)
+    }
+#else
+    public func push(_ message: String = "") -> CallStack {
+        let item = CallStackItem(message: message)
+        return push(item: item)
+    }
+#endif
+}
+
+//extension CallStack: Equatable {
+//    static func == (lhs: CallStack, rhs: CallStack) -> Bool { lhs.storage == 
rhs.storage }
+//}
diff --git a/TalerWallet1/Helper/Controller+playSound.swift 
b/TalerWallet1/Helper/Controller+playSound.swift
index 31aca38..bf6a784 100644
--- a/TalerWallet1/Helper/Controller+playSound.swift
+++ b/TalerWallet1/Helper/Controller+playSound.swift
@@ -4,12 +4,14 @@
  */
 import Foundation
 import AVFoundation
+import UIKit
 
 extension Controller {
 
     /// 0 = failure, 1 = received, 2 = sent
-    func playSound(_ number: Int) {
+    @MainActor func playSound(_ number: Int) {
         var soundID: SystemSoundID = 0
+        let notificationGenerator = useHaptics ? 
UINotificationFeedbackGenerator() : nil
         if number > 9 {
             soundID = UInt32(number)
         } else {
@@ -34,5 +36,8 @@ extension Controller {
                 AudioServicesPlaySystemSound(soundID);
             }
         }
+        if let notificationGenerator {
+            notificationGenerator.notificationOccurred(number == 0 ? .error : 
.success)
+        }
     }
 }
diff --git a/TalerWallet1/Helper/Font+Taler.swift 
b/TalerWallet1/Helper/Font+Taler.swift
index bc0511a..ef4e612 100644
--- a/TalerWallet1/Helper/Font+Taler.swift
+++ b/TalerWallet1/Helper/Font+Taler.swift
@@ -6,108 +6,251 @@ import SwiftUI
 
 // Use enums for multiple font types and functions for the set custom font.
 
-fileprivate let ATKINSON   = "AtkinsonHyperlegible-"
-fileprivate let NUNITO     = "Nunito-"
-
-fileprivate let REGULAR    = "Regular"
-fileprivate let BOLD       = "Bold"
-fileprivate let BOLDITALIC = "BoldItalic"
-fileprivate let ITALIC     = "Italic"
-
-extension Font {
-    enum TalerFont {
-        case regular
-        case bold
-        case boldItalic
-        case italic
-        case custom(String)
-
-        var value: String {
-            switch self {
-                case .regular: return REGULAR
-                case .bold: return BOLD
-                case .boldItalic: return BOLDITALIC
-                case .italic: return ITALIC
-
-                case .custom(let name):
-                    return name
-            }
+fileprivate let ATKINSON    = "AtkinsonHyperlegible-"
+fileprivate let NUNITO      = "Nunito-"
+
+fileprivate let REGULAR     = "Regular"
+fileprivate let BOLD        = "Bold"
+fileprivate let BLACK       = "Black"
+fileprivate let BLACKITALIC = "BlackItalic"
+fileprivate let BOLDITALIC  = "BoldItalic"
+fileprivate let ITALIC      = "Italic"
+
+struct TalerFont {
+    static var atkinson: Font {
+        Font.custom(ATKINSON + REGULAR, size: 24, relativeTo: .title2)
+    }
+    static var nunito: Font {
+        Font.custom(NUNITO + REGULAR, size: 24, relativeTo: .title2)
+    }
+    static var nunitoItalic: Font {
+        Font.custom(NUNITO + ITALIC, size: 24, relativeTo: .title2)
+    }
+
+    static func atkinson(size: CGFloat, relativeTo style: UIFont.TextStyle) -> 
UIFont {
+        if let font = UIFont(name: ATKINSON + REGULAR, size: size) {
+            let fontMetrics = UIFontMetrics(forTextStyle: style)
+            return fontMetrics.scaledFont(for: font)
+        } else {
+            return UIFont.preferredFont(forTextStyle: style)
+        }
+    }
+    static func nunito(size: CGFloat, relativeTo: UIFont.TextStyle) -> UIFont {
+        if let font = UIFont(name: NUNITO + REGULAR, size: size) {
+            let fontMetrics = UIFontMetrics(forTextStyle: relativeTo)
+            return fontMetrics.scaledFont(for: font)
+        } else {
+            return UIFont.preferredFont(forTextStyle: relativeTo)
+        }
+    }
+    static func nunitoItalic(size: CGFloat, relativeTo: UIFont.TextStyle) -> 
UIFont {
+        if let font = UIFont(name: NUNITO + ITALIC, size: size) {
+            let fontMetrics = UIFontMetrics(forTextStyle: relativeTo)
+            return fontMetrics.scaledFont(for: font)
+        } else {
+            return UIFont.preferredFont(forTextStyle: relativeTo)
+        }
+    }
+
+    static func talerFont(_ talerFont: Int, size: CGFloat, relativeTo style: 
UIFont.TextStyle) -> UIFont {
+        if talerFont != 0 {
+            let uiFont: UIFont = (talerFont == 1) ? TalerFont.atkinson(size: 
size, relativeTo: style)
+                               : (talerFont == 2) ? TalerFont.nunito(size: 
size, relativeTo: style)
+                                                  : 
TalerFont.nunitoItalic(size: size, relativeTo: style)
+            return uiFont
+        } else {
+            return UIFont.preferredFont(forTextStyle: style)
         }
     }
+}
 
-    static func talerFont(_ type: TalerFont, size: CGFloat = 17) -> Font {
-        return .custom(type.value, size: size)
+struct AccessibleFont {
+    var regular: Font
+    var bold: Font
+    static var talerFont: Int {
+        if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] 
== "1" {
+            3
+        } else {
+            Controller.shared.talerFont
+        }
     }
 
-    static func talerFontName(_ index: Int) -> String {
-        if index == 1 {
-            return ATKINSON
+    init(_ base: String, size: CGFloat, relativeTo: Font.TextStyle, isBold: 
Bool = false) {
+        if AccessibleFont.talerFont == 0 {
+            self.regular = .system(relativeTo)
+            self.bold = .system(relativeTo).bold()      // why is this allowed 
here (iOS-15) ??? should give compiler error
+                                                        // bold() for Font 
needs iOS-16
+                                                        // Text has a function 
bold(), needs iOS-13, but that shouldn't matter here
+        } else if isBold && AccessibleFont.talerFont >= 2 {
+            // Nunito has Black Variants, but AtkinsonHyperlegible doesn't
+            self.regular = Font.custom(base + (AccessibleFont.talerFont == 2 ? 
BOLD : BOLDITALIC), size: size, relativeTo: relativeTo)
+            self.bold = Font.custom(base + (AccessibleFont.talerFont == 2 ? 
BLACK : BLACKITALIC), size: size, relativeTo: relativeTo)
         } else {
-            return NUNITO
+            self.regular = Font.custom(base + (AccessibleFont.talerFont > 2 ? 
ITALIC : REGULAR), size: size, relativeTo: relativeTo)
+            self.bold = Font.custom(base + (AccessibleFont.talerFont > 2 ? 
BOLDITALIC : BOLD), size: size, relativeTo: relativeTo)
+        }
+    }
+
+    init(regular: Font, bold: Font) {
+        self.regular = regular
+        self.bold = bold
+    }
+
+    func value(_ legibilityWeight: LegibilityWeight?) -> Font {
+        switch legibilityWeight {
+            case .bold:     // should increase Font.Weight by 2
+                // ultraLight => light
+                // thin => regular
+                // light => medium
+                // regular => semibold
+                // medium => bold
+                // semibold => heavy
+                // bold => black
+                return bold
+            default:
+                return regular
         }
     }
+}
+
+extension AccessibleFont {
+    static var fontName: String {
+        (talerFont == 1) ? ATKINSON
+                         : NUNITO
+    }
 
-    static var talerLargeTitle: Font {
-        Controller.shared.talerFont == 0 ? .largeTitle :
-            .custom(talerFontName(Controller.shared.talerFont) + REGULAR, 
size: 38, relativeTo: .largeTitle)
-    } // 34 -> 38
-    static var talerTitle: Font {
-        Controller.shared.talerFont == 0 ? .title :
-            .custom(talerFontName(Controller.shared.talerFont) + REGULAR, 
size: 31, relativeTo: .title)
-    } // 28 -> 31
-    static var talerTitle2: Font {
-        Controller.shared.talerFont == 0 ? .title2 :
-            .custom(talerFontName(Controller.shared.talerFont) + REGULAR, 
size: 25, relativeTo: .title2)
-    } // 22 -> 25
-    static var talerTitle3: Font {
-        Controller.shared.talerFont == 0 ? .title3 :
-            .custom(talerFontName(Controller.shared.talerFont) + REGULAR, 
size: 23, relativeTo: .title3)
-    } // 20 -> 23
-    static var talerHeadline: Font {
-        Controller.shared.talerFont == 0 ? .headline :
-            .custom(talerFontName(Controller.shared.talerFont) + BOLD, size: 
19, relativeTo: .headline)
-    } // 17 bold -> 19 bold
-    static var talerBody: Font {
-        Controller.shared.talerFont == 0 ? .body :
-            .custom(talerFontName(Controller.shared.talerFont) + REGULAR, 
size: 19, relativeTo: .body)
-    } // 17 -> 19
-    static var talerCallout: Font {
-        Controller.shared.talerFont == 0 ? .callout :
-            .custom(talerFontName(Controller.shared.talerFont) + REGULAR, 
size: 18, relativeTo: .callout)
-    } // 16 -> 18
-    static var talerSubheadline: Font {
-        Controller.shared.talerFont == 0 ? .subheadline :
-            .custom(talerFontName(Controller.shared.talerFont) + REGULAR, 
size: 17, relativeTo: .subheadline)
-    } // 15 -> 17
-    static var talerFootnote: Font {
-        Controller.shared.talerFont == 0 ? .footnote :
-            .custom(talerFontName(Controller.shared.talerFont) + REGULAR, 
size: 15, relativeTo: .footnote)
-    } // 13 -> 15
-    static var talerCaption: Font {
-        Controller.shared.talerFont == 0 ? .caption :
-            .custom(talerFontName(Controller.shared.talerFont) + REGULAR, 
size: 13, relativeTo: .caption)
-    } // 12 -> 13
-    static var talerCaption2: Font {
-        Controller.shared.talerFont == 0 ? .caption2 :
-            .custom(talerFontName(Controller.shared.talerFont) + REGULAR, 
size: 12, relativeTo: .caption2)
-    } // 11 -> 12
+    static var largeTitle:  AccessibleFont { AccessibleFont(fontName, size: 
38, relativeTo: .largeTitle) }  // 34 -> 38
+    static var title:       AccessibleFont { AccessibleFont(fontName, size: 
31, relativeTo: .title) }       // 28 -> 31
+    static var title2:      AccessibleFont { AccessibleFont(fontName, size: 
25, relativeTo: .title2) }      // 22 -> 25
+    static var title3:      AccessibleFont { AccessibleFont(fontName, size: 
23, relativeTo: .title3) }      // 20 -> 23
+    static var headline:    AccessibleFont { AccessibleFont(fontName, size: 
19, relativeTo: .headline, isBold: true) } // 17 bold -> 19 bold
+    static var body:        AccessibleFont { AccessibleFont(fontName, size: 
19, relativeTo: .body) }        // 17 -> 19
+    static var callout:     AccessibleFont { AccessibleFont(fontName, size: 
18, relativeTo: .callout) }     // 16 -> 18
+    static var subheadline: AccessibleFont { AccessibleFont(fontName, size: 
17, relativeTo: .subheadline) } // 15 -> 17
+    static var footnote:    AccessibleFont { AccessibleFont(fontName, size: 
15, relativeTo: .footnote) }    // 13 -> 15
+    static var caption:     AccessibleFont { AccessibleFont(fontName, size: 
13, relativeTo: .caption) }     // 12 -> 13
+//    static var caption2:    AccessibleFont { AccessibleFont(fontName, size: 
12, relativeTo: .caption2) }    // 11 -> 12
 }
 
+struct AccessibilityFontViewModifier: ViewModifier {
+    @Environment(\.legibilityWeight) private var legibilityWeight
+
+    var font: AccessibleFont
+
+    func body(content: Content) -> some View {
+        content.font(font.value(legibilityWeight))
+    }
+}
+
+extension View {
+    func accessibilityFont(_ font: AccessibleFont) -> some View {
+        return self.modifier(AccessibilityFontViewModifier(font: font))
+    }
+}
+// MARK: -
+/// This works on-the-fly to update NavigationTitles when you change the font
+struct NavigationBarBuilder: UIViewControllerRepresentable {
+    var build: (UINavigationController) -> Void = { _ in }
+
+    func makeUIViewController(context: 
UIViewControllerRepresentableContext<NavigationBarBuilder>) -> UIViewController 
{
+        UIViewController()
+    }
+
+    func updateUIViewController(_ uiViewController: UIViewController,
+                                           context: 
UIViewControllerRepresentableContext<NavigationBarBuilder>) {
+        if let navigationController = uiViewController.navigationController {
+            self.build(navigationController)
+        }
+    }
+}
+
+/// This works only once. Each following call does nothing - including 
(re-)setting to nil
+@MainActor
+struct TalerNavBar: ViewModifier {
+    let talerFont: Int
+
+    static func setNavBarFonts(talerFont: Int) -> Void {
+        let navBarAppearance = UINavigationBar.appearance()
+        navBarAppearance.titleTextAttributes = nil
+        navBarAppearance.largeTitleTextAttributes = nil
+        if talerFont != 0 {
+            navBarAppearance.titleTextAttributes = [.font: 
TalerFont.talerFont(talerFont, size: 24, relativeTo: .title2)]
+            navBarAppearance.largeTitleTextAttributes = [.font: 
TalerFont.talerFont(talerFont, size: 38, relativeTo: .largeTitle)]
+        }
+    }
+
+    init(_ talerFont: Int) {
+        self.talerFont = talerFont
+        TalerNavBar.setNavBarFonts(talerFont: talerFont)
+    }
+
+    func body(content: Content) -> some View {
+        let _ = TalerNavBar.setNavBarFonts(talerFont: talerFont)
+        content
+    }
+
+}
+
+extension View {
+    @MainActor func talerNavBar(talerFont: Int) -> some View {
+        self.modifier(TalerNavBar(talerFont))
+    }
+}
+
+
+#if false
+//init() {
+//    NavigationBarConfigurator.configureTitles()
+//}
+struct NavigationBarConfigurator {
+    static func configureTitles() {
+        let appearance = UINavigationBarAppearance()
+        let design = UIFontDescriptor.SystemDesign.rounded
+        if let descriptorWithDesign = 
UIFontDescriptor.preferredFontDescriptor(withTextStyle: .largeTitle)
+            .withDesign(design),
+           let descriptorWithTraits = 
descriptorWithDesign.withSymbolicTraits(.traitBold) {
+            let font = UIFont(descriptor: descriptorWithTraits, size: 34)
+            appearance.largeTitleTextAttributes = [.font: font, 
.foregroundColor: UIColor.label]
+        }
+        if let smallTitleDescriptorWithDesign = 
UIFontDescriptor.preferredFontDescriptor(withTextStyle: .headline)              
                                                .withDesign(design) {
+            let smallTitleFont = UIFont(descriptor: 
smallTitleDescriptorWithDesign, size: 24)
+            appearance.titleTextAttributes = [.font:smallTitleFont, 
.foregroundColor: UIColor.label]
+        }
+        UINavigationBar.appearance().standardAppearance = appearance
+    }
+}
+#endif
+// MARK: -
 struct ContentViewFonts: View {
+    //    let myWeight: Font.Weight
     var body: some View {
         VStack {
-            Text("Text demo")
-                .font(.talerFont(.regular))
-            Text("Text demo")
-                .font(.talerFont(.italic))
-            Text("Text demo")
-                .font(.talerFont(.bold))
-            Text("Text demo")
-                .font(.talerFont(.boldItalic))
-
-            Text("Text demo")
-                .font(.talerBody)
+            HStack {
+                Text("title a")
+                Text("bold").bold()
+            }
+            .accessibilityFont(.title)
+            .padding()
 
+            HStack {
+                Text("title2 a")
+                Text("italic").italic()
+                Text("bold").bold()
+            }
+            .accessibilityFont(.title2)
+            .padding()
+            Text("headline")
+                .accessibilityFont(.headline)
+                .padding(.top)
+            Text("headline bold")
+                .bold()
+                .accessibilityFont(.headline)
+                .padding(.bottom)
+            Text("title2 bold italic")
+                .bold()
+                .italic()
+                .accessibilityFont(.title2)
+                .padding()
         }
     }
 }
diff --git a/TalerWallet1/Helper/KeyboardResponder.swift 
b/TalerWallet1/Helper/KeyboardResponder.swift
index c5d9cde..c8e496d 100644
--- a/TalerWallet1/Helper/KeyboardResponder.swift
+++ b/TalerWallet1/Helper/KeyboardResponder.swift
@@ -19,6 +19,7 @@
 import Combine
 import UIKit
 
+@MainActor
 public final class KeyboardResponder: ObservableObject {
 
     @Published public var keyboardHeight: CGFloat = 0
diff --git a/TalerWallet1/Helper/UIScreen+screenSize.swift 
b/TalerWallet1/Helper/UIScreen+screenSize.swift
new file mode 100644
index 0000000..3fe327e
--- /dev/null
+++ b/TalerWallet1/Helper/UIScreen+screenSize.swift
@@ -0,0 +1,11 @@
+/*
+ * This file is part of GNU Taler, ©2022-23 Taler Systems S.A.
+ * See LICENSE.md
+ */
+import SwiftUI
+
+extension UIScreen {
+    static let screenWidth = UIScreen.main.bounds.size.width
+    static let screenHeight = UIScreen.main.bounds.size.height
+    static let screenSize = UIScreen.main.bounds.size
+}
diff --git a/TalerWallet1/Helper/View+Notification.swift 
b/TalerWallet1/Helper/View+Notification.swift
index 00760bf..a68ddb7 100644
--- a/TalerWallet1/Helper/View+Notification.swift
+++ b/TalerWallet1/Helper/View+Notification.swift
@@ -64,7 +64,7 @@ extension View {
         }
     }
 
-    func onAppEnteredBackground(
+    @MainActor func onAppEnteredBackground(
         perform action: @escaping () -> Void
     ) -> some View {
         onNotification(
diff --git a/TalerWallet1/Helper/View+dismissTop.swift 
b/TalerWallet1/Helper/View+dismissTop.swift
index 40f0084..46ea8c7 100644
--- a/TalerWallet1/Helper/View+dismissTop.swift
+++ b/TalerWallet1/Helper/View+dismissTop.swift
@@ -22,7 +22,7 @@ import SwiftUI
 /// A presented sheet (SwiftUI view) doesn't always close when calling 
"dismiss()" provided by @Environment(\.dismiss),
 /// so we are walking the view stack to find the top presentedViewController 
(UIKit) and dismiss it.
 extension View {
-    public func dismissTop(animated: Bool = true) {
+    @MainActor public func dismissTop(animated: Bool = true) {
         let windows = UIApplication.shared.connectedScenes.compactMap {
             ($0 as? UIWindowScene)?.keyWindow       // TODO: iPad might have 
more than 1 window
         }
diff --git a/TalerWallet1/Helper/View+flippedDirection.swift 
b/TalerWallet1/Helper/View+flippedDirection.swift
new file mode 100644
index 0000000..35a8b70
--- /dev/null
+++ b/TalerWallet1/Helper/View+flippedDirection.swift
@@ -0,0 +1,21 @@
+/*
+ * This file is part of GNU Taler, ©2022-23 Taler Systems S.A.
+ * See LICENSE.md
+ */
+import SwiftUI
+
+struct FlippedDirection: ViewModifier {
+    @Environment(\.layoutDirection) var layoutDirection
+
+    func body(content: Content) -> some View {
+        let isLeft = layoutDirection == .leftToRight
+        content
+            .environment(\.layoutDirection, isLeft ? .rightToLeft : 
.leftToRight)
+    }
+}
+
+extension View {
+    func flippedDirection() -> some View {
+        self.modifier(FlippedDirection())
+    }
+}
diff --git a/TalerWallet1/Model/Model+Balances.swift 
b/TalerWallet1/Model/Model+Balances.swift
index f1a651c..3c5c585 100644
--- a/TalerWallet1/Model/Model+Balances.swift
+++ b/TalerWallet1/Model/Model+Balances.swift
@@ -8,7 +8,7 @@ fileprivate let ASYNCDELAY: UInt = 0   //set e.g to 6 or 9 
seconds for debugging
 
 // MARK: -
 /// A currency balance
-struct Balance: Decodable, Hashable {
+struct Balance: Decodable, Hashable, Sendable {
     var available: Amount
     var scopeInfo: ScopeInfo
     var requiresUserInput: Bool
@@ -36,14 +36,14 @@ fileprivate struct Balances: WalletBackendFormattedRequest {
 
     struct Args: Encodable {}                           // no arguments needed
 
-    struct Response: Decodable {                        // list of balances
+    struct Response: Decodable, Sendable {              // list of balances
         var balances: [Balance]
     }
 }
 // MARK: -
 extension WalletModel {
     /// fetch Balances from Wallet-Core. No networking involved
-    @MainActor func balancesM()
+    @MainActor func balancesM(_ stack: CallStack)
       async -> [Balance] {          // M for MainActor
         do {
             let request = Balances()
diff --git a/TalerWallet1/Model/Model+Exchange.swift 
b/TalerWallet1/Model/Model+Exchange.swift
index f52ee75..304ef06 100644
--- a/TalerWallet1/Model/Model+Exchange.swift
+++ b/TalerWallet1/Model/Model+Exchange.swift
@@ -7,22 +7,38 @@ import taler_swift
 import SymLog
 fileprivate let ASYNCDELAY: UInt = 0   //set e.g to 6 or 9 seconds for 
debugging
 
+enum ExchangeEntryStatus: String, Codable {
+    case preset
+    case ephemeral
+    case used
+}
+
+enum ExchangeUpdateStatus: String, Codable {
+    case initial
+    case initialUpdate = "initial(update)"
+    case suspended
+    case failed
+    case outdatedUpdate = "outdated(update)"
+    case ready
+    case readyUpdate = "ready(update)"
+}
 // MARK: -
 /// The result from wallet-core's ListExchanges
 struct Exchange: Codable, Hashable, Identifiable {
     static func == (lhs: Exchange, rhs: Exchange) -> Bool {
         return lhs.exchangeBaseUrl == rhs.exchangeBaseUrl &&
-        lhs.exchangeStatus == rhs.exchangeStatus &&
-        lhs.permanent == rhs.permanent
+        lhs.tosStatus == rhs.tosStatus &&
+        lhs.exchangeEntryStatus == rhs.exchangeEntryStatus &&
+        lhs.exchangeUpdateStatus == rhs.exchangeUpdateStatus
     }
 
     var exchangeBaseUrl: String
     var currency: String?
     var paytoUris: [String]
-    var tosStatus: String
-    var exchangeStatus: String
+    var tosStatus: ExchangeTosStatus
+    var exchangeEntryStatus: ExchangeEntryStatus
+    var exchangeUpdateStatus: ExchangeUpdateStatus
     var ageRestrictionOptions: [Int]
-    var permanent: Bool
     var lastUpdateErrorInfo: ExchangeError?
 
     var id: String {
diff --git a/TalerWallet1/Model/Model+Transactions.swift 
b/TalerWallet1/Model/Model+Transactions.swift
index 0795255..f3fb35b 100644
--- a/TalerWallet1/Model/Model+Transactions.swift
+++ b/TalerWallet1/Model/Model+Transactions.swift
@@ -108,7 +108,7 @@ struct ResumeTransaction: WalletBackendFormattedRequest {
 // MARK: -
 extension WalletModel {
     /// ask wallet-core for its list of transactions filtered by searchString
-    func transactionsT(currency: String? = nil, searchString: String? = nil)
+    func transactionsT(_ stack: CallStack, currency: String? = nil, 
searchString: String? = nil)
     async -> [Transaction] {                                          // might 
be called from a background thread itself
         do {
             let request = GetTransactions(currency: currency, search: 
searchString)
@@ -119,9 +119,9 @@ extension WalletModel {
         }
     }
     /// fetch transactions from Wallet-Core. No networking involved
-    @MainActor func transactionsMA(currency: String? = nil, searchString: 
String? = nil)
+    @MainActor func transactionsMA(_ stack: CallStack, currency: String? = 
nil, searchString: String? = nil)
     async -> [Transaction] {    // M for MainActor
-        return await transactionsT(currency: currency, searchString: 
searchString)
+        return await transactionsT(stack.push(), currency: currency, 
searchString: searchString)
     }
 
     /// abort the specified transaction from Wallet-Core. No networking 
involved
diff --git a/TalerWallet1/Model/Model+Withdraw.swift 
b/TalerWallet1/Model/Model+Withdraw.swift
index 754c9dd..7b8124c 100644
--- a/TalerWallet1/Model/Model+Withdraw.swift
+++ b/TalerWallet1/Model/Model+Withdraw.swift
@@ -72,6 +72,9 @@ enum ExchangeTosStatus: String, Codable {
     case changed = "changed"
     case notFound = "not-found"
     case unknown = "unknown"
+    case pending
+    case proposed
+//    case accepted
 }
 struct ExchangeTermsOfService: Decodable {
     var currentEtag: String
diff --git a/TalerWallet1/Model/WalletModel.swift 
b/TalerWallet1/Model/WalletModel.swift
index eea87e4..508fbf9 100644
--- a/TalerWallet1/Model/WalletModel.swift
+++ b/TalerWallet1/Model/WalletModel.swift
@@ -24,7 +24,7 @@ class WalletModel: ObservableObject {
 #endif
         let sendTime = Date.now
         do {
-            let (response, id) = try await 
WalletCore.shared.sendFormattedRequest(request: request)
+            let (response, id) = try await 
WalletCore.shared.sendFormattedRequest(request)
 #if !DEBUG
             let timeUsed = Date.now - sendTime
             logger.log("received: \(request.operation(), privacy: .public) 
(\(id, privacy: .public)) after \(timeUsed.milliseconds, privacy: .public) ms")
diff --git a/TalerWallet1/Views/Balances/BalanceRowView.swift 
b/TalerWallet1/Views/Balances/BalanceRowView.swift
index 89a5a15..b2b0a31 100644
--- a/TalerWallet1/Views/Balances/BalanceRowView.swift
+++ b/TalerWallet1/Views/Balances/BalanceRowView.swift
@@ -15,16 +15,13 @@ struct BalanceButton: View {
     var body: some View {
         Button(action: rowAction) {
             VStack(alignment: .trailing, spacing: 0) {
-                HStack(alignment: .firstTextBaseline, spacing: 0) {
-                    Text("B", comment: "the first letter of Balance - or leave 
empty")
-                        .font(.title2)
-                    Text("alance", comment: "the remaining letters of Balance 
- or all if you left B empty")
-                        .font(.footnote).bold()
-                }
+                Text("Balance", comment: "Balance in main view")
+                    .bold()         // in iOS-15 defined for Text, but not for 
Font (only iOS-16)
                 Text(verbatim: "\(amount.valueStr)")  // TODO: 
CurrencyFormatter?
-                    .font(.title)
+                    .accessibilityFont(.title)
                     .monospacedDigit()
             }
+            .accessibilityFont(.subheadline)
         }   .disabled(false)
             .accessibilityElement(children: 
/*@START_MENU_TOKEN@*/.ignore/*@END_MENU_TOKEN@*/)
             .accessibilityLabel("Balance \(amount.readableDescription)")    // 
TODO: CurrencyFormatter!
@@ -42,7 +39,7 @@ struct BalanceRowView: View {
 
     func needVStack(_ amount: Amount) -> Bool {
         // Sizes: 320 (SE), 375 (X, Xs, 12, 13 mini), 390 (12,13,14), 414 
(Plus, Max), 428 (Pro Max)
-        guard 350 < UIScreen.main.bounds.width else {return true}   // always 
for iPhone SE 1st Gen
+        guard 350 < UIScreen.screenWidth else {return true}   // always for 
iPhone SE 1st Gen
         var count = amount.currencyStr.count
 //        print(sizeCategory)
         switch sizeCategory {
@@ -89,9 +86,9 @@ struct BalanceRowView: View {
 struct BalanceRowView_Previews: PreviewProvider {
     static var previews: some View {
         List {
-            BalanceRowView(amount: try! Amount(fromString: "TestKUDOS" + 
":1234.56"),
+            BalanceRowView(amount: try! Amount(fromString: TESTCURRENCY + 
":1234.56"),
                            sendAction: {}, recvAction: {}, rowAction: {})
-            BalanceRowView(amount: try! Amount(fromString: "KUDOS" + 
":1234.56"),
+            BalanceRowView(amount: try! Amount(fromString: DEMOCURRENCY + 
":1234.56"),
                            sendAction: {}, recvAction: {}, rowAction: {})
         }
     }
diff --git a/TalerWallet1/Views/Balances/BalancesListView.swift 
b/TalerWallet1/Views/Balances/BalancesListView.swift
index 934acb2..f1b091e 100644
--- a/TalerWallet1/Views/Balances/BalancesListView.swift
+++ b/TalerWallet1/Views/Balances/BalancesListView.swift
@@ -10,6 +10,7 @@ import AVFoundation
 /// This view shows the list of balances / currencies, each in its own section
 struct BalancesListView: View {
     private let symLog = SymLogV()
+    let stack: CallStack
     let navTitle: String
     let hamburgerAction: () -> Void
 
@@ -69,10 +70,12 @@ struct BalancesListView: View {
         })
     }
 
-    private func reloadAction() async -> Int {
-        let reloaded = await model.balancesM()
+    /// runs on MainActor if called in some Task {}
+    @discardableResult
+    private func reloadAction(_ stack: CallStack) async -> Int {
+        let reloaded = await model.balancesM(stack.push())
         let count = reloaded.count
-        balances = reloaded
+        balances = reloaded         // redraw
         return count
     }
 
@@ -81,7 +84,7 @@ struct BalancesListView: View {
         let _ = Self._printChanges()
         let _ = symLog.vlog()       // just to get the # to compare it with 
.onAppear & onDisappear
 #endif
-        Content(symLog: symLog, balances: $balances,
+        Content(symLog: symLog, stack: stack.push(), balances: $balances,
                 centsToTransfer: $centsToTransfer, summary: $summary,
                 reloadAction: reloadAction)
             .navigationTitle(navTitle)
@@ -91,14 +94,13 @@ struct BalancesListView: View {
                 if balances.isEmpty {
                     WalletEmptyView()
                         .refreshable {  // already async
-                            symLog.log("refreshing")
-                            let count = await reloadAction()
+                            symLog.log("empty refreshing")
+                            let count = await reloadAction(stack.push("empty 
refreshing"))
                             if count > 0 {
 //                                postNotificationM(.BalanceReloaded)
                                 NotificationCenter.default.post(name: 
.BalanceReloaded, object: nil)
                             }
                         }
-
                 }
             }
             .alert("Scanning QR-codes requires access to the camera",
@@ -110,12 +112,12 @@ struct BalancesListView: View {
                 DebugViewC.shared.setViewID(VIEW_BALANCES)
             }
             .sheet(isPresented: $showQRScanner) {
-                let sheet = AnyView(QRSheet())
+                let sheet = AnyView(QRSheet(stack: stack.push()))
                 Sheet(sheetView: sheet)
             } // sheet
             .task {
                 symLog.log(".task getBalances")
-                _ = await reloadAction()
+                await reloadAction(stack.push(".task"))
             } // task
     }
 }
@@ -123,11 +125,13 @@ struct BalancesListView: View {
 extension BalancesListView {
     struct Content: View {
         let symLog: SymLogV?
+        let stack: CallStack
         @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
         @Binding var balances: [Balance]
         @Binding var centsToTransfer: UInt64
         @Binding var summary: String
-        var reloadAction: () async -> Int
+//        @discardableResult
+        var reloadAction: (_ stack: CallStack) async -> Int
 
         @State private var isActive = true
         @State private var shouldReload = false
@@ -140,14 +144,15 @@ extension BalancesListView {
             Group { // necessary for .backslide transition (bug in SwiftUI)
                 let count = balances.count
                 List(balances, id: \.self) { balance in
-                    BalancesSectionView(balance: balance,
+                    BalancesSectionView(stack: stack.push(),
+                                        balance: balance,
                                    sectionCount: count,
                                 centsToTransfer: $centsToTransfer,
                                         summary: $summary)
                 }
                 .refreshable {  // already async
                     symLog?.log("refreshing")
-                    let count = await reloadAction()
+                    let count = await reloadAction(stack.push("refreshing"))
                     if count > 0 {
 //                        postNotificationM(.BalanceReloaded)
                         NotificationCenter.default.post(name: 
.BalanceReloaded, object: nil)
@@ -160,7 +165,7 @@ extension BalancesListView {
                 if shouldReload {
                     shouldReload = false
                     symLog?.log(".onAppear ==>  shouldReload was true, 
reloading now")
-                    Task { await reloadAction() }
+                    Task { await reloadAction(stack.push("shouldReload")) } // 
runs on MainActor
                 }
             }
             .onDisappear() {
@@ -171,7 +176,7 @@ extension BalancesListView {
                 // doesn't need to be received on main thread because we just 
reload in a background task anyway
                 if isActive {
                     symLog?.log(".onNotification(.BalanceChange) ==> reload")
-                    Task { await reloadAction() }
+                    Task { await reloadAction(stack.push(".BalanceChange")) }
                 } else {
                     symLog?.log(".onNotification(.BalanceChange) ==> reload 
postponed, shouldReload = true")
                     shouldReload = true
diff --git a/TalerWallet1/Views/Balances/BalancesSectionView.swift 
b/TalerWallet1/Views/Balances/BalancesSectionView.swift
index 6423dbe..3bd555f 100644
--- a/TalerWallet1/Views/Balances/BalancesSectionView.swift
+++ b/TalerWallet1/Views/Balances/BalancesSectionView.swift
@@ -15,7 +15,8 @@ import SymLog
 /// optional:   Suspended / Aborting / Aborted / Expired
 
 struct BalancesSectionView: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
     let balance: Balance
     let sectionCount: Int
     @Binding var centsToTransfer: UInt64
@@ -65,17 +66,17 @@ struct BalancesSectionView: View {
 #endif
         let currency = balance.available.currencyStr
         let reloadCompleted = {
-            transactions = await model.transactionsT(currency: currency)
+            transactions = await model.transactionsT(stack.push(), currency: 
currency)
             completedTransactions = 
WalletModel.completedTransactions(transactions)
 //            sectionID = UUID()
         }
         let reloadPending = {
-            transactions = await model.transactionsT(currency: currency)
+            transactions = await model.transactionsT(stack.push(), currency: 
currency)
             pendingTransactions = WalletModel.pendingTransactions(transactions)
 //            sectionID = UUID()
         }
         let reloadUncompleted = {
-            transactions = await model.transactionsT(currency: currency)
+            transactions = await model.transactionsT(stack.push(), currency: 
currency)
             uncompletedTransactions = 
WalletModel.uncompletedTransactions(transactions)
 //            sectionID = UUID()
         }
@@ -83,15 +84,17 @@ struct BalancesSectionView: View {
         Section {
             if "KUDOS" == currency && !balance.available.isZero {
                 Text("You can spend these KUDOS in the [Demo 
Shop](https://shop.demo.taler.net), or send them to another wallet.")
+                    .accessibilityFont(.body)
                     .multilineTextAlignment(.leading)
             }
-            NavigationLinksView(balance: balance,
-                        centsToTransfer: $centsToTransfer,
-                                summary: $summary,
-//                         buttonSelected: $buttonSelected,
-                  completedTransactions: $completedTransactions,
-                        reloadAllAction: reloadCompleted,
-                        reloadOneAction: reloadOneAction)
+            NavigationLinksView(stack: stack.push(),
+                              balance: balance,
+                      centsToTransfer: $centsToTransfer,
+                              summary: $summary,
+//                       buttonSelected: $buttonSelected,
+                completedTransactions: $completedTransactions,
+                      reloadAllAction: reloadCompleted,
+                      reloadOneAction: reloadOneAction)
             let hasPending = pendingTransactions.count > 0
             if hasPending {
                 let (pendingIncoming, pendingOutgoing) = 
computePending(currency: currency)
@@ -99,11 +102,13 @@ struct BalancesSectionView: View {
                 NavigationLink {
 //let _ = print("button: Pending Transactions: \(currency)")
                     LazyView {
-                        TransactionsListView(navTitle: String(localized: 
"Pending"), currency: currency,
-                                         transactions: pendingTransactions,
-                                           showUpDown: false,
-                                      reloadAllAction: reloadPending,
-                                      reloadOneAction: reloadOneAction)
+                        TransactionsListView(stack: stack.push(),
+                                          navTitle: String(localized: 
"Pending"),
+                                          currency: currency,
+                                      transactions: pendingTransactions,
+                                        showUpDown: false,
+                                   reloadAllAction: reloadPending,
+                                   reloadOneAction: reloadOneAction)
                     }
                 } label: {
                     VStack(spacing: 6) {
@@ -118,6 +123,7 @@ struct BalancesSectionView: View {
                         }
                         if rows == 0 {
                             Text("Some pending transactions")
+                                .accessibilityFont(.body)
                         }
                     }
                 }
@@ -127,12 +133,13 @@ struct BalancesSectionView: View {
                 NavigationLink {
 //let _ = print("button: Uncompleted Transactions: \(currency)")
                     LazyView {
-                        TransactionsListView(navTitle: String(localized: 
"Uncompleted"),
-                                             currency: currency,
-                                         transactions: uncompletedTransactions,
-                                           showUpDown: false,
-                                      reloadAllAction: reloadUncompleted,
-                                      reloadOneAction: reloadOneAction)
+                        TransactionsListView(stack: stack.push(),
+                                          navTitle: String(localized: 
"Uncompleted"),
+                                          currency: currency,
+                                      transactions: uncompletedTransactions,
+                                        showUpDown: false,
+                                   reloadAllAction: reloadUncompleted,
+                                   reloadOneAction: reloadOneAction)
                     }
                 } label: {
                     UncompletedRowView(uncompletedTransactions: 
$uncompletedTransactions)
@@ -140,13 +147,16 @@ struct BalancesSectionView: View {
 
             }
         } header: {
-            Text(currency)
-                .font(.title)
+            HStack (alignment: .bottom, spacing: 10) {
+                BarGraph(transactions: $completedTransactions, barHeight: 10)
+                Text(currency)
+                    .accessibilityFont(.title2)
+            }
         }.id(sectionID)
         .task {
 //            if shownSectionID != sectionID {
-                symLog.log("task for BalancesSectionView \(sectionID) - reload 
Transactions")
-                let response = await model.transactionsT(currency: currency)
+                symLog.log("task for \(sectionID) - reload Transactions")
+                let response = await model.transactionsT(stack.push("task for 
\(sectionID) - reload Transactions"), currency: currency)
                 transactions = response
                 pendingTransactions = WalletModel.pendingTransactions(response)
                 uncompletedTransactions = 
WalletModel.uncompletedTransactions(response)
@@ -172,18 +182,20 @@ struct BalancesSectionView: View {
                 let slice = sortedTransactions.prefix(3)
                 let threeTransactions = Array(slice)
                 TransactionsRowsView(symLog: symLog,
-                                     currency: currency,
-                                     transactions: threeTransactions,
-                                     reloadOneAction: reloadOneAction)
+                                      stack: stack.push(),
+                                   currency: currency,
+                               transactions: threeTransactions,
+                            reloadOneAction: reloadOneAction)
             } header: {
                 Text("Recent transactions")
-                    .font(.callout)
+                    .accessibilityFont(.callout)
             }
         }
     } // body
 }
 
 fileprivate struct NavigationLinksView : View {
+    let stack: CallStack
     let balance: Balance
 //    let sectionCount: Int
     @Binding var centsToTransfer: UInt64
@@ -198,25 +210,29 @@ fileprivate struct NavigationLinksView : View {
         let currency = balance.available.currencyStr
         HStack(spacing: 0) {
             NavigationLink(destination: LazyView {
-                SendAmount(amountAvailable: balance.available,
-                           centsToTransfer: $centsToTransfer,
-                                   summary: $summary)
+                SendAmount(stack: stack.push(),
+                 amountAvailable: balance.available,
+                 centsToTransfer: $centsToTransfer,
+                         summary: $summary)
             }, tag: 1, selection: $buttonSelected
             ) { EmptyView() }.frame(width: 0).opacity(0).hidden()           // 
SendAmount
 
             NavigationLink(destination: LazyView {
-                RequestPayment(scopeInfo: balance.scopeInfo,
-                         centsToTransfer: $centsToTransfer,
-                                 summary: $summary)
+                RequestPayment(stack: stack.push(),
+                           scopeInfo: balance.scopeInfo,
+                     centsToTransfer: $centsToTransfer,
+                             summary: $summary)
             }, tag: 2, selection: $buttonSelected
             ) { EmptyView() }.frame(width: 0).opacity(0).hidden()           // 
RequestPayment
 
             NavigationLink(destination: LazyView {
-                TransactionsListView(navTitle: String(localized: 
"Transactions"), currency: currency,
-                                 transactions: completedTransactions,
-                                   showUpDown: true,
-                              reloadAllAction: reloadAllAction,
-                              reloadOneAction: reloadOneAction)
+                TransactionsListView(stack: stack.push(),
+                                  navTitle: String(localized: "Transactions"),
+                                  currency: currency,
+                              transactions: completedTransactions,
+                                showUpDown: true,
+                           reloadAllAction: reloadAllAction,
+                           reloadOneAction: reloadOneAction)
             }, tag: 3, selection: $buttonSelected
             ) { EmptyView() }.frame(width: 0).opacity(0).hidden()           // 
TransactionsListView
 
@@ -231,7 +247,7 @@ fileprivate struct NavigationLinksView : View {
     }
 }
 // MARK: -
-#if DEBUG
+#if false   // model crashes
 fileprivate struct BindingViewContainer : View {
     @State var centsToTransfer: UInt64 = 333
     @State private var summary: String = "bla-bla"
diff --git a/TalerWallet1/Views/Balances/PendingRowView.swift 
b/TalerWallet1/Views/Balances/PendingRowView.swift
index 657b1a6..c883f57 100644
--- a/TalerWallet1/Views/Balances/PendingRowView.swift
+++ b/TalerWallet1/Views/Balances/PendingRowView.swift
@@ -12,26 +12,24 @@ struct PendingRowView: View {
 
     var body: some View {
         HStack {
+            let pendingColor = WalletColors().pendingColor(incoming)
             Image(systemName: incoming ? "text.badge.plus"
                                        : "text.badge.minus")
-                .font(.largeTitle)
-//                .foregroundColor(WalletColors().pendingColor)    // pending 
is always gray
-                .foregroundColor(WalletColors().pendingColor(incoming))
+                .foregroundColor(pendingColor)
+                .accessibilityFont(.largeTitle)
                 .accessibility(hidden: true)
 
             Spacer()
             Text("pending\n" + (incoming ? "incoming" : "outgoing"))
+                .accessibilityFont(.body)
             Spacer()
             VStack(alignment: .trailing) {
                 let sign = incoming ? "+" : "-"
                 let valueStr = sign + amount.valueStr
                 Text(valueStr)
-                    .font(.title)
-                    .foregroundColor(WalletColors().pendingColor(incoming))
+                    .foregroundColor(pendingColor)
+                    .accessibilityFont(.title)
                     .monospacedDigit()
-//                Text("PENDING")
-//                    .font(.callout)
-//                    .foregroundColor(WalletColors().pendingColor(incoming))
             }
         }
         .accessibilityElement(children: .combine)
diff --git a/TalerWallet1/Views/Balances/UncompletedRowView.swift 
b/TalerWallet1/Views/Balances/UncompletedRowView.swift
index b4637a2..a9436b6 100644
--- a/TalerWallet1/Views/Balances/UncompletedRowView.swift
+++ b/TalerWallet1/Views/Balances/UncompletedRowView.swift
@@ -14,7 +14,7 @@ struct UncompletedRowView: View {
         HStack {
             Spacer()
             Text("\(count) uncompleted transactions")
-                .font(.title2)
+                .accessibilityFont(.title2)
                 .foregroundColor(WalletColors().uncompletedColor)
             Spacer()
         }
diff --git a/TalerWallet1/Views/Exchange/ExchangeListView.swift 
b/TalerWallet1/Views/Exchange/ExchangeListView.swift
index f36d510..3d1a1f2 100644
--- a/TalerWallet1/Views/Exchange/ExchangeListView.swift
+++ b/TalerWallet1/Views/Exchange/ExchangeListView.swift
@@ -9,6 +9,7 @@ import SymLog
 /// This view shows the list of exchanges
 struct ExchangeListView: View {
     private let symLog = SymLogV(0)
+    let stack: CallStack
     let navTitle: String
     var hamburgerAction: () -> Void
 
@@ -24,7 +25,7 @@ struct ExchangeListView: View {
     }
 
     func addExchange(_ exUrl: String) -> Void {
-        Task {
+        Task { // runs on MainActor
             symLog.log("adding: \(exUrl)")
             do {
                 try await model.addExchange(url: exUrl)
@@ -50,9 +51,10 @@ struct ExchangeListView: View {
 
         //Text("Exchanges...")
         Content(symLog: symLog,
-                exchanges: $exchanges,
-                centsToTransfer: $centsToTransfer,
-                reloadAction: reloadAction)
+                 stack: stack.push(),
+             exchanges: $exchanges,
+       centsToTransfer: $centsToTransfer,
+          reloadAction: reloadAction)
         .navigationTitle(navTitle)
         .navigationBarItems(leading: HamburgerButton(action: hamburgerAction),
                             trailing: PlusButton(action: plusAction)
@@ -60,6 +62,7 @@ struct ExchangeListView: View {
         .overlay {
             if exchanges.isEmpty {
                 Text("No Exchanges yet...")
+                    .accessibilityFont(.body)
             }
         }
         .task {
@@ -83,6 +86,7 @@ struct ExchangeListView: View {
 extension ExchangeListView {
     struct Content: View {
         let symLog: SymLogV?
+        let stack: CallStack
         @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
         @Binding var exchanges: [Exchange]
         @Binding var centsToTransfer: UInt64
@@ -109,7 +113,9 @@ extension ExchangeListView {
             let sortedDict = dict.sorted{ $0.key < $1.key}
             Group { // necessary for .backslide transition (bug in SwiftUI)
                 List(sortedDict, id: \.key) { key, value in
-                    ExchangeSectionView(currency: key, exchanges: value, 
centsToTransfer: $centsToTransfer)
+                    ExchangeSectionView(stack: stack.push(),
+                                     currency: key, exchanges: value,
+                              centsToTransfer: $centsToTransfer)
                 }
                 .refreshable {
                     symLog?.log("refreshing")
@@ -123,7 +129,7 @@ extension ExchangeListView {
             .onNotification(.ExchangeAdded) { notification in
                 // doesn't need to be received on main thread because we just 
reload in the background anyway
                 symLog?.log(".onNotification(.ExchangeAdded) ==> reloading 
exchanges")
-                Task { await reloadAction() }
+                Task { await reloadAction() } // runs on MainActor
             }
         } // body
     }
diff --git a/TalerWallet1/Views/Exchange/ExchangeSectionView.swift 
b/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
index ffe53dc..a87ea0b 100644
--- a/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
+++ b/TalerWallet1/Views/Exchange/ExchangeSectionView.swift
@@ -6,6 +6,7 @@ import SwiftUI
 import taler_swift
 
 struct ExchangeRowView: View {
+    let stack: CallStack
     let exchange: Exchange
     let currency: String
     @Binding var centsToTransfer: UInt64
@@ -16,14 +17,16 @@ struct ExchangeRowView: View {
 
         HStack(spacing: 0) {    // can't use the built in Label because it 
adds the accessory arrow
             Text(baseURL.trimURL())
+                .accessibilityFont(.body)
 
             NavigationLink(destination: LazyView {
                 EmptyView()     // TODO: Deposit
             }, tag: 1, selection: $buttonSelected
             ) { EmptyView() }.frame(width: 0).opacity(0)
             NavigationLink(destination: LazyView {
-                ManualWithdraw(exchange: exchange,
-                               centsToTransfer: $centsToTransfer)
+                ManualWithdraw(stack: stack.push(),
+                            exchange: exchange,
+                     centsToTransfer: $centsToTransfer)
             }, tag: 2, selection: $buttonSelected
             ) { EmptyView() }.frame(width: 0).opacity(0)
         }.listRowSeparator(.hidden)
@@ -46,6 +49,7 @@ struct ExchangeRowView: View {
 ///         currency
 /// [Deposit Coins]  [Withdraw Coins]
 struct ExchangeSectionView: View {
+    let stack: CallStack
     let currency: String
     let exchanges: [Exchange]
 
@@ -58,12 +62,15 @@ struct ExchangeSectionView: View {
 #endif
         Section {
             ForEach(exchanges) { exchange in
-                ExchangeRowView(exchange: exchange, currency: currency, 
centsToTransfer: $centsToTransfer)
+                ExchangeRowView(stack: stack.push(),
+                             exchange: exchange,
+                             currency: currency,
+                      centsToTransfer: $centsToTransfer)
             }
             .accessibilityElement(children: .combine)
         } header: {
             Text(currency)
-                .font(.title)
+                .accessibilityFont(.title)
         }
     }
 }
@@ -76,18 +83,18 @@ struct ExchangeRow_Container : View {
         let exchange1 = Exchange(exchangeBaseUrl: ARS_AGE_EXCHANGE,
                                         currency: LONGCURRENCY,
                                        paytoUris: [],
-                                       tosStatus: "tosStatus",
-                                  exchangeStatus: "exchangeStatus",
-                           ageRestrictionOptions: [12,16],
-                                       permanent: true)
+                                       tosStatus: .pending,
+                             exchangeEntryStatus: .preset,
+                            exchangeUpdateStatus: .initial,
+                           ageRestrictionOptions: [12,16])
         let exchange2 = Exchange(exchangeBaseUrl: ARS_EXP_EXCHANGE,
                                         currency: LONGCURRENCY,
                                        paytoUris: [],
-                                       tosStatus: "tosStatus",
-                                  exchangeStatus: "exchangeStatus",
-                           ageRestrictionOptions: [],
-                                       permanent: false)
-            ExchangeSectionView(currency: LONGCURRENCY, exchanges: [exchange1, 
exchange2],
+                                       tosStatus: .proposed,
+                             exchangeEntryStatus: .ephemeral,
+                            exchangeUpdateStatus: .ready,
+                           ageRestrictionOptions: [])
+        ExchangeSectionView(stack: CallStack("Preview"), currency: 
LONGCURRENCY, exchanges: [exchange1, exchange2],
                                 centsToTransfer: $centsToTransfer)
     }
 }
diff --git a/TalerWallet1/Views/Exchange/ManualWithdraw.swift 
b/TalerWallet1/Views/Exchange/ManualWithdraw.swift
index 5486073..5e45416 100644
--- a/TalerWallet1/Views/Exchange/ManualWithdraw.swift
+++ b/TalerWallet1/Views/Exchange/ManualWithdraw.swift
@@ -8,7 +8,8 @@ import SymLog
 
 // Will be called by the user tapping "Withdraw Coins" in the exchange list
 struct ManualWithdraw: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
 
     let exchange: Exchange
     @Binding var centsToTransfer: UInt64
@@ -39,7 +40,7 @@ struct ManualWithdraw: View {
                                currency: currency, amountEffective: 
withdrawalAmountDetails?.amountEffective)
                 Text(exchange.exchangeBaseUrl.trimURL())
                     .multilineTextAlignment(.center)
-//                    .font(.title3)
+                    .accessibilityFont(.body)
 
                 let disabled = (centsToTransfer == 0) || someCoins.invalid || 
someCoins.tooMany
                 if !disabled {
@@ -51,23 +52,17 @@ struct ManualWithdraw: View {
 //                                                                       : 
selectedAge
 //let _ = print(selectedAge, restrictAge)
                             NavigationLink(destination: LazyView {
-                                ManualWithdrawDone(exchange: exchange,
-                                            centsToTransfer: centsToTransfer)
-//                                                restrictAge: restrictAge)
+                                ManualWithdrawDone(stack: stack.push(),
+                                                exchange: exchange,
+                                         centsToTransfer: centsToTransfer)
+//                                              restrictAge: restrictAge)
                             }) {
                                 Text("Confirm Withdrawal")      // 
VIEW_WITHDRAW_ACCEPT
                             }.buttonStyle(TalerButtonStyle(type: .prominent))
                         } else {
-                            Text("You must accept the Terms of Service first 
before you can withdraw electronic cash to your wallet.")
-                                .multilineTextAlignment(.leading)
-                                .padding()
-                            NavigationLink(destination: LazyView {
-                                WithdrawTOSView(exchangeBaseUrl: 
exchange.exchangeBaseUrl,
-                                                         viewID: 
VIEW_WITHDRAW_TOS,
-                                                   acceptAction: nil)         
// pop back to here
-                            }) {
-                                Text("Read Terms of Service")  // 
VIEW_WITHDRAW_TOS
-                            }.buttonStyle(TalerButtonStyle(type: .prominent))
+                            ToSButtonView(exchangeBaseUrl: 
exchange.exchangeBaseUrl,
+                                                   viewID: VIEW_WITHDRAW_TOS,
+                                                      p2p: false)
                         }
                     }
                 } // disabled
@@ -108,13 +103,14 @@ struct ManualWithdraw_Container : View {
         let exchange = Exchange(exchangeBaseUrl: DEMOEXCHANGE,
                                        currency: LONGCURRENCY,
                                       paytoUris: [],
-                                      tosStatus: "tosStatus",
-                                 exchangeStatus: "exchangeStatus",
-                          ageRestrictionOptions: [],
-                                      permanent: false)
-        ManualWithdraw(exchange: exchange,
-                centsToTransfer: $centsToTransfer,
-        withdrawalAmountDetails: details)
+                                      tosStatus: .pending,
+                            exchangeEntryStatus: .preset,
+                           exchangeUpdateStatus: .initial,
+                          ageRestrictionOptions: [])
+        ManualWithdraw(stack: CallStack("Preview"),
+                    exchange: exchange,
+             centsToTransfer: $centsToTransfer,
+     withdrawalAmountDetails: details)
     }
 }
 
diff --git a/TalerWallet1/Views/Exchange/ManualWithdrawDone.swift 
b/TalerWallet1/Views/Exchange/ManualWithdrawDone.swift
index e5d3b20..df5b3b1 100644
--- a/TalerWallet1/Views/Exchange/ManualWithdrawDone.swift
+++ b/TalerWallet1/Views/Exchange/ManualWithdrawDone.swift
@@ -7,7 +7,8 @@ import taler_swift
 import SymLog
 
 struct ManualWithdrawDone: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
     let navTitle = String(localized: "Wire Transfer")
 
     let exchange: Exchange
@@ -30,15 +31,16 @@ struct ManualWithdrawDone: View {
 #endif
         Group {
             if let transactionId {
-                TransactionDetailView(transactionId: transactionId,
-                                       reloadAction: reloadOneAction,
-                                           navTitle: navTitle,
-                                         doneAction: 
ViewState.shared.popToRootView,
-                                        abortAction: nil,
-                                       deleteAction: nil,
-                                         failAction: nil,
-                                      suspendAction: nil,
-                                       resumeAction: nil)
+                TransactionDetailView(stack: stack.push(),
+                              transactionId: transactionId,
+                               reloadAction: reloadOneAction,
+                                   navTitle: navTitle,
+                                 doneAction: ViewState.shared.popToRootView,
+                                abortAction: nil,
+                               deleteAction: nil,
+                                 failAction: nil,
+                              suspendAction: nil,
+                               resumeAction: nil)
                 .navigationBarBackButtonHidden(true)
                 .interactiveDismissDisabled()           // can only use "Done" 
button to dismiss
 //                .navigationTitle(navTitle)
@@ -71,12 +73,13 @@ struct ManualWithdrawDone_Container : View {
         let exchange = Exchange(exchangeBaseUrl: DEMOEXCHANGE,
                                        currency: LONGCURRENCY,
                                       paytoUris: [],
-                                      tosStatus: "tosStatus",
-                                 exchangeStatus: "exchangeStatus",
-                          ageRestrictionOptions: [],
-                                      permanent: false)
-        ManualWithdrawDone(exchange: exchange,
-                    centsToTransfer: centsToTransfer)
+                                      tosStatus: .pending,
+                            exchangeEntryStatus: .preset,
+                           exchangeUpdateStatus: .initial,
+                          ageRestrictionOptions: [])
+        ManualWithdrawDone(stack: CallStack("Preview"),
+                        exchange: exchange,
+                 centsToTransfer: centsToTransfer)
     }
 }
 
diff --git a/TalerWallet1/Views/Exchange/QuiteSomeCoins.swift 
b/TalerWallet1/Views/Exchange/QuiteSomeCoins.swift
index aa00586..961d9d6 100644
--- a/TalerWallet1/Views/Exchange/QuiteSomeCoins.swift
+++ b/TalerWallet1/Views/Exchange/QuiteSomeCoins.swift
@@ -47,7 +47,7 @@ extension SomeCoins {
 }
 // MARK: -
 struct QuiteSomeCoins: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
     let someCoins: SomeCoins
     let shouldShowFee: Bool
     let currency: String
@@ -57,11 +57,12 @@ struct QuiteSomeCoins: View {
         if !someCoins.invalid {
             if !someCoins.tooMany {
                 if someCoins.manyCoins {
-                    Text(someCoins.quiteSome ? "Warning: It will take quite 
some time to encrypt this amount!"
-                                             : "Warning: It will take some 
time to encrypt this amount.")
+                    Text(someCoins.quiteSome ? "Warning: It will take quite 
some time to withdraw this amount!"
+                                             : "Warning: It will take some 
time to withdraw this amount.")
+                    .foregroundColor(someCoins.quiteSome ? .red : .primary)
+                    .accessibilityFont(.body)
                     .multilineTextAlignment(.leading)
                     .padding(.vertical, 6)
-                    .foregroundColor(someCoins.quiteSome ? .red : .primary)
                 } // warnings
             }
         }
@@ -71,6 +72,7 @@ struct QuiteSomeCoins: View {
                 : someCoins.hasFee ? "- \(someCoins.fee) fee"
                                    : "No withdrawal fee")
             .foregroundColor((someCoins.invalid || someCoins.tooMany || 
someCoins.hasFee) ? .red : .primary)
+            .accessibilityFont(.body)
 //            .padding(4)
         }
     }
diff --git a/TalerWallet1/Helper/AgePicker.swift 
b/TalerWallet1/Views/HelperViews/AgePicker.swift
similarity index 94%
rename from TalerWallet1/Helper/AgePicker.swift
rename to TalerWallet1/Views/HelperViews/AgePicker.swift
index 2622f39..d833037 100644
--- a/TalerWallet1/Helper/AgePicker.swift
+++ b/TalerWallet1/Views/HelperViews/AgePicker.swift
@@ -32,7 +32,7 @@ struct AgePicker: View {
                 HStack {
                     Text("If this wallet belongs to a child or teenager, the 
generated electronic cash should be age-restricted:")
                         .multilineTextAlignment(.leading)
-                        .font(.footnote)
+                        .accessibilityFont(.footnote)
                     Spacer()
                 }.padding(.top)
                 Picker("Select age", selection: $selectedAge) {
@@ -42,6 +42,7 @@ struct AgePicker: View {
                                           : "\(index) years").tag(index)
                     }
                 }
+                .accessibilityFont(.body)
             }
         }
     }
diff --git a/TalerWallet1/Views/HelperViews/AmountView.swift 
b/TalerWallet1/Views/HelperViews/AmountView.swift
index 8702ac5..f635dc0 100644
--- a/TalerWallet1/Views/HelperViews/AmountView.swift
+++ b/TalerWallet1/Views/HelperViews/AmountView.swift
@@ -15,15 +15,15 @@ struct AmountView: View {
             Text(title)
                 .fixedSize(horizontal: false, vertical: true)       // wrap in 
scrollview
                 .multilineTextAlignment(.leading)
-                .font(.body)
+                .accessibilityFont(.body)
             HStack {
                 Spacer()
                 Text(value)
                     .fixedSize(horizontal: false, vertical: true)   // wrap in 
scrollview
                     .multilineTextAlignment(.center)
-                    .font(large ? .title : .title2)
-//                    .fontWeight(large ? .medium : .regular)       // 
@available(iOS 16.0, *)
                     .foregroundColor(color)
+                    .accessibilityFont(large ? .title : .title2)
+//                    .fontWeight(large ? .medium : .regular)       // 
@available(iOS 16.0, *)
                     .monospacedDigit()
                 Spacer()
             }
diff --git a/TalerWallet1/Views/HelperViews/BarGraph.swift 
b/TalerWallet1/Views/HelperViews/BarGraph.swift
new file mode 100644
index 0000000..a842c01
--- /dev/null
+++ b/TalerWallet1/Views/HelperViews/BarGraph.swift
@@ -0,0 +1,87 @@
+/*
+ * This file is part of GNU Taler, ©2022-23 Taler Systems S.A.
+ * See LICENSE.md
+ */
+import SwiftUI
+
+struct BarGraph: View {
+    @Binding var transactions: [Transaction]
+    let barHeight : Double
+
+    func maxValue(_ someTransactions: [Transaction]) -> Double {
+        var maxValue = 0.0
+        for transaction in someTransactions {
+            let value = transaction.common.amountEffective.value
+            if value > maxValue {
+                maxValue = value
+            }
+        }
+        return maxValue
+    }
+
+    var body: some View {
+        let slice = transactions.prefix(8)
+        let eightTransactions: [Transaction] = Array(slice)
+        let count = eightTransactions.count
+        let maxValue = maxValue(eightTransactions)
+
+        HStack(alignment: .firstTextBaseline, spacing: 1) {
+#if DEBUG
+//            Text("first")
+#endif
+            if count > 0 {
+                ForEach(Array(eightTransactions.enumerated()), id: \.element) 
{ index, transaction in
+                    let common = transaction.common
+                    let incoming = common.incoming()
+                    let netto = common.amountEffective.value
+                    let valueColored = barHeight * netto / maxValue
+                    let valueTransparent = barHeight - valueColored
+//                    let _ = print("max: \(maxValue), ", incoming ? "+" : 
"-", netto)
+                    VStack(spacing: 0) {
+                        Rectangle()
+                            .opacity(0.001)
+                            .frame (width: 3, height: incoming ? 
valueTransparent : barHeight )
+                        Rectangle()
+                            .foregroundColor(incoming ? .green : .red)
+                            .frame (width: 3, height: valueColored )
+                        Rectangle()
+                            .opacity(0.001)
+                            .frame (width: 3, height: incoming ? barHeight : 
valueTransparent)
+                    }
+                }
+            }
+//            if count < 8 {
+//                ForEach(count...8, id: \.self) {_ in
+//                    Rectangle()
+//                        .opacity(0.001)
+//                        .frame (width: 3, height: barHeight * 2 )
+//                }
+//            }
+#if DEBUG
+//            Text("last")
+#endif
+        }
+        .accessibilityHidden(true)      // cannot speak out this bar chart info
+//        .flippedDirection()         // draw first array item on trailing edge
+    }
+}
+
+
+
+#if false
+#Preview {
+    var sampleBars: [BarData] {
+        var tempBars = [BarData]()
+
+        for _ in 1...8 {
+            let rand = Double.random(in: -100.0...100.0)
+
+            let bar = BarData(value: rand)
+            tempBars.append(bar)
+        }
+        return tempBars
+    }
+
+    return BarGraph(bars: sampleBars)
+}
+#endif
diff --git a/TalerWallet1/Views/HelperViews/Buttons.swift 
b/TalerWallet1/Views/HelperViews/Buttons.swift
index a1e80b4..650ad36 100644
--- a/TalerWallet1/Views/HelperViews/Buttons.swift
+++ b/TalerWallet1/Views/HelperViews/Buttons.swift
@@ -18,77 +18,76 @@ extension ShapeStyle where Self == Color {
 }
 
 struct HamburgerButton : View  {
-    var font: Font?
     let action: () -> Void
 
     var body: some View {
         Button(action: action) {
             Image(systemName: "line.3.horizontal")
         }
-            .font(font ?? .title)
+        .accessibilityFont(.title)
+        .accessibilityLabel("Main Menu")
     }
 }
 
 struct QRButton : View  {
-    var font: Font?
     let action: () -> Void
 
     var body: some View {
         Button(action: action) {
             Image(systemName: "qrcode.viewfinder")
         }
-        .font(font ?? .title)
+        .accessibilityFont(.title)
         .accessibilityLabel("Scan QR codes")
     }
 }
 
 struct PlusButton : View  {
-    var font: Font?
     let action: () -> Void
 
     var body: some View {
         Button(action: action) {
             Image(systemName: "plus")
         }
-            .font(font ?? .title)
+        .accessibilityFont(.title)
+        .accessibilityLabel("Add...")
     }
 }
 
 struct ArrowUpButton : View  {
-    var font: Font?
     let action: () -> Void
 
     var body: some View {
         Button(action: action) {
             Image(systemName: "arrow.up.to.line")
         }
-            .font(font ?? .title3)
+        .accessibilityFont(.title2)
+        .accessibilityLabel("Scroll up")
     }
 }
 
 struct ArrowDownButton : View  {
-    var font: Font?
     let action: () -> Void
 
     var body: some View {
         Button(action: action) {
             Image(systemName: "arrow.down.to.line")
         }
-            .font(font ?? .title3)
+        .accessibilityFont(.title2)
+        .accessibilityLabel("Scroll down")
     }
 }
 
 struct ReloadButton : View  {
     let disabled: Bool
-    var font: Font?
     let action: () -> Void
 
     var body: some View {
         Button(action: action) {
             Image(systemName: "arrow.clockwise")
         }
-            .font(font ?? .title)
-            .disabled(disabled)
+        .accessibilityFont(.title)
+        .accessibilityLabel("Reload")
+        .disabled(disabled)
     }
 }
 
@@ -172,8 +171,8 @@ struct TalerButtonStyle: ButtonStyle {
                                     : Alignment.trailing
             configuration.label
                 .multilineTextAlignment(aligned)
-                .font(.title3)
-//                .font(narrow ? .title3 : .title2)
+                .accessibilityFont(.title3)
+//                                  narrow ? .title3 : .title2
                 .frame(minWidth: 0, maxWidth: narrow ? nil : .infinity, 
alignment: aligned2)
                 .padding(.vertical, 10)
                 .padding(.horizontal, 6)
diff --git a/TalerWallet1/Views/HelperViews/CopyShare.swift 
b/TalerWallet1/Views/HelperViews/CopyShare.swift
index b3de098..c3825fd 100644
--- a/TalerWallet1/Views/HelperViews/CopyShare.swift
+++ b/TalerWallet1/Views/HelperViews/CopyShare.swift
@@ -32,10 +32,12 @@ struct CopyButton: View {
                 }
             }
         }
+        .accessibilityFont(.body)
         .disabled(!isEnabled)
     }
 }
 // MARK: -
+@MainActor
 struct ShareButton: View {
     private let symLog = SymLogV(0)
     @Environment(\.isEnabled) private var isEnabled: Bool
@@ -54,6 +56,7 @@ struct ShareButton: View {
                 Text("Share")
             }
         }
+        .accessibilityFont(.body)
         .disabled(!isEnabled)
     }
 }
diff --git a/TalerWallet1/Views/HelperViews/CurrencyField.swift 
b/TalerWallet1/Views/HelperViews/CurrencyField.swift
index 91cb70a..2072b02 100644
--- a/TalerWallet1/Views/HelperViews/CurrencyField.swift
+++ b/TalerWallet1/Views/HelperViews/CurrencyField.swift
@@ -22,6 +22,7 @@
 import SwiftUI
 import UIKit
 
+@MainActor
 public struct CurrencyField: View {
     @Binding var value: UInt64
     var currency: String
@@ -88,6 +89,7 @@ class NoCaretTextField: UITextField {
     }
 }
 
+@MainActor
 struct CurrencyInputField: UIViewRepresentable {
     @Binding var value: UInt64
     var formatter: NumberFormatter
@@ -97,11 +99,11 @@ struct CurrencyInputField: UIViewRepresentable {
         Coordinator(self)
     }
 
-    public func becomeFirstResponder() -> Void {
+    @MainActor public func becomeFirstResponder() -> Void {
         textField.becomeFirstResponder()
     }
 
-    public func resignFirstResponder() -> Void {
+    @MainActor public func resignFirstResponder() -> Void {
         textField.resignFirstResponder()
     }
 
diff --git a/TalerWallet1/Views/HelperViews/CurrencyInputView.swift 
b/TalerWallet1/Views/HelperViews/CurrencyInputView.swift
index e4405b3..f89a702 100644
--- a/TalerWallet1/Views/HelperViews/CurrencyInputView.swift
+++ b/TalerWallet1/Views/HelperViews/CurrencyInputView.swift
@@ -16,12 +16,12 @@ struct CurrencyInputView: View {
         VStack (alignment: .leading) {
             Text(title)
 //                .padding(.top)
-                .font(.title3)
+                .accessibilityFont(.title3)
             currencyField
                 .frame(maxWidth: .infinity, alignment: .trailing)
                 .foregroundColor(WalletColors().fieldForeground)     // text 
color
                 .background(WalletColors().fieldBackground)
-                .font(.title2)
+                .accessibilityFont(.title2)
                 .textFieldStyle(.roundedBorder)
         }.onAppear {   // make CurrencyField show the keyboard after 0.4 
seconds
             if hasBeenShown {
diff --git a/TalerWallet1/Views/HelperViews/LaunchAnimationView.swift 
b/TalerWallet1/Views/HelperViews/LaunchAnimationView.swift
index 761bf73..de4712d 100644
--- a/TalerWallet1/Views/HelperViews/LaunchAnimationView.swift
+++ b/TalerWallet1/Views/HelperViews/LaunchAnimationView.swift
@@ -9,7 +9,7 @@ struct LaunchAnimationView: View {
     var body: some View {
         ZStack {
             Color(.systemGray6).ignoresSafeArea()
-            RotatingTaler(size: (350 < UIScreen.main.bounds.width) ? 200 : 
250, rotationEnabled: $rotationEnabled)
+            RotatingTaler(size: (350 < UIScreen.screenWidth) ? 200 : 250, 
rotationEnabled: $rotationEnabled)
         }
     }
 }
diff --git a/TalerWallet1/Views/HelperViews/QRCodeDetailView.swift 
b/TalerWallet1/Views/HelperViews/QRCodeDetailView.swift
index 091a1ab..435e4ea 100644
--- a/TalerWallet1/Views/HelperViews/QRCodeDetailView.swift
+++ b/TalerWallet1/Views/HelperViews/QRCodeDetailView.swift
@@ -17,10 +17,11 @@ struct QRCodeDetailView: View {
             VStack (alignment: .leading) {
                 Text("Either copy and send this link:")
                     .multilineTextAlignment(.leading)
-                    .font(.title3)
+                    .accessibilityFont(.title3)
                     .padding(.vertical)
 
                 Text(talerURI)
+                    .accessibilityFont(.title3)
                     .multilineTextAlignment(.center)
                     .fixedSize(horizontal: false, vertical: true)       // 
wrap in scrollview
                     .padding(.bottom)
@@ -40,7 +41,7 @@ struct QRCodeDetailView: View {
                 Text(amountStr)
                     .fixedSize(horizontal: false, vertical: true)       // 
wrap in scrollview
 //                    .padding(.top, 30)
-                    .font(.title3)
+                    .accessibilityFont(.title3)
                 HStack {
                     Spacer()
                     QRGeneratorView(text: talerURI)
diff --git a/TalerWallet1/Views/HelperViews/TextFieldAlert.swift 
b/TalerWallet1/Views/HelperViews/TextFieldAlert.swift
index e307ff1..f665620 100644
--- a/TalerWallet1/Views/HelperViews/TextFieldAlert.swift
+++ b/TalerWallet1/Views/HelperViews/TextFieldAlert.swift
@@ -17,7 +17,9 @@ struct TextFieldAlert: ViewModifier {
                 .disabled(isPresented)
             if isPresented {
                 VStack {
-                    Text(title).font(.headline).padding()
+                    Text(title)
+                        .accessibilityFont(.headline)
+                        .padding()
                     TextField(placeholder, text: 
$text).textFieldStyle(.roundedBorder).padding()
                     Divider()
                     HStack {
@@ -34,6 +36,7 @@ struct TextFieldAlert: ViewModifier {
                             action(text)
                             withAnimation { isPresented.toggle() }
                         }
+//                        .accessibilityFont(.talerBody)     TODO: check
                         Spacer()
                     }
                 }
diff --git a/TalerWallet1/Views/HelperViews/ToSButtonView.swift 
b/TalerWallet1/Views/HelperViews/ToSButtonView.swift
new file mode 100644
index 0000000..9799c5d
--- /dev/null
+++ b/TalerWallet1/Views/HelperViews/ToSButtonView.swift
@@ -0,0 +1,35 @@
+//
+//  ToSButtonView.swift
+//  TalerWallet
+//
+//  Created by Marc Stibane on 2023-09-05.
+//  Copyright © 2023 Taler. All rights reserved.
+//
+
+import SwiftUI
+
+struct ToSButtonView: View {
+    let exchangeBaseUrl: String?
+    let viewID: Int         // either VIEW_WITHDRAW_TOS or SHEET_WITHDRAW_TOS
+    let p2p: Bool
+
+    var body: some View {
+        let hint = p2p ? String(localized: "You must accept the Exchange's 
Terms of Service first before you can receive electronic cash in your wallet.", 
comment: "P2P Receive")
+                       : String(localized: "You must accept the Exchange's 
Terms of Service first before you can use it to withdraw electronic cash to 
your wallet.")
+        Text(hint)
+            .accessibilityFont(.body)
+            .multilineTextAlignment(.leading)
+            .padding()
+        NavigationLink(destination: LazyView {
+            WithdrawTOSView(exchangeBaseUrl: exchangeBaseUrl,
+                                     viewID: viewID,
+                               acceptAction: nil)         // pop back to here
+        }) {
+            Text("Terms of Service")  // VIEW_WITHDRAW_TOS
+        }.buttonStyle(TalerButtonStyle(type: .prominent))
+    }
+}
+
+#Preview {
+    ToSButtonView(exchangeBaseUrl: nil, viewID: 0, p2p: false)
+}
diff --git a/TalerWallet1/Views/HelperViews/TransactionButton.swift 
b/TalerWallet1/Views/HelperViews/TransactionButton.swift
index 4c17030..0ac465e 100644
--- a/TalerWallet1/Views/HelperViews/TransactionButton.swift
+++ b/TalerWallet1/Views/HelperViews/TransactionButton.swift
@@ -19,7 +19,7 @@ struct TransactionButton: View {
                               :  isDestructive ? .destructive
                                                : nil
         Button(role: role, action: {
-            Task {
+            Task { // runs on MainActor
                 disabled = true     // don't try this more than once
                 do {
                     try await action(transactionId)
@@ -69,7 +69,7 @@ struct TransactionButton: View {
                     }
                 }
             }
-            .font(.title)
+            .accessibilityFont(.title2)
             .frame(maxWidth: .infinity)
         })
         .buttonStyle(.bordered)
diff --git a/TalerWallet1/Views/Main/MainView.swift 
b/TalerWallet1/Views/Main/MainView.swift
index 70c8a23..7743cf9 100644
--- a/TalerWallet1/Views/Main/MainView.swift
+++ b/TalerWallet1/Views/Main/MainView.swift
@@ -15,11 +15,13 @@ struct LazyView<Content: View>: View {
 
 struct MainView: View {
     private let symLog = SymLogV(0)
+    let stack: CallStack
     @EnvironmentObject private var viewState: ViewState         // 
popToRootView()
     @EnvironmentObject private var controller: Controller
     @State private var sheetPresented = false
     @State private var urlToOpen: URL? = nil
     @Binding var soundPlayed: Bool
+    @AppStorage("talerFont") var talerFont: Int = 0         // extension 
mustn't define this, so it must be here
 
     func sheetDismissed() -> Void {
         symLog.log("sheet dismiss")
@@ -31,7 +33,7 @@ struct MainView: View {
 #endif
         Group {
             if controller.backendState == .ready {
-                Content(symLog: symLog)
+                Content(symLog: symLog, stack: stack.push(), talerFont: 
$talerFont)
                 // any change to rootViewId triggers popToRootView behaviour
                     .id(viewState.rootViewId)
                     .onAppear() {
@@ -58,7 +60,7 @@ struct MainView: View {
             urlToOpen = url     // raise sheet
         }
         .sheet(item: $urlToOpen, onDismiss: sheetDismissed) { url in
-            let sheet = AnyView(URLSheet(urlToOpen: url))
+            let sheet = AnyView(URLSheet(stack: stack.push(), urlToOpen: url))
             Sheet(sheetView: sheet)
         }
     } // body
@@ -67,10 +69,13 @@ struct MainView: View {
 extension MainView {
     struct Content: View {
         let symLog: SymLogV?
-
+        let stack: CallStack
+        @Binding var talerFont: Int
         @State var sidebarVisible: Bool = false
         func hamburgerAction() {
-            sidebarVisible = !sidebarVisible
+            withAnimation(.easeInOut(duration: 0.25)) {
+                sidebarVisible = !sidebarVisible
+            }
         }
 
         let balances = String(localized: "Balances")
@@ -79,13 +84,15 @@ extension MainView {
         var views: [SidebarItem] {[
             SidebarItem(name: balances,
                     sysImage: "creditcard.fill",        // TODO: Wallet Icon
-                        view: AnyView(BalancesListView(navTitle: balances,
-                                                hamburgerAction: 
hamburgerAction)
+                        view: AnyView(BalancesListView(stack: 
stack.push(balances),
+                                                    navTitle: balances,
+                                             hamburgerAction: hamburgerAction)
                                      )),
             SidebarItem(name: exchanges,
                     sysImage: "building.columns",
-                        view: AnyView(ExchangeListView(navTitle: exchanges,
-                                                hamburgerAction: 
hamburgerAction)
+                        view: AnyView(ExchangeListView(stack: 
stack.push(exchanges),
+                                                    navTitle: exchanges,
+                                             hamburgerAction: hamburgerAction)
                                      )),
             SidebarItem(name: settings,    // TODO: "About"?
                     sysImage: "gearshape.fill",
@@ -107,13 +114,25 @@ extension MainView {
                             .id(views[currentView].name)
                             .frame(maxWidth: .infinity, maxHeight: .infinity, 
alignment: .center)
                             .transition(.backslide)
-                    }
+                    }   .id(talerFont)
                         .navigationBarTitleDisplayMode(.automatic)
-                }.navigationViewStyle(.stack)
-                // The side view is on top of the current view
-                SideBarView(views: views,
+                        .background(NavigationBarBuilder { 
navigationController in
+                            //                            
navigationController.navigationBar.barTintColor = .red
+                            
navigationController.navigationBar.titleTextAttributes =
+                                [.font: TalerFont.talerFont(talerFont, size: 
24, relativeTo: .title2)]
+                            
navigationController.navigationBar.largeTitleTextAttributes =
+                                [.font: TalerFont.talerFont(talerFont, size: 
38, relativeTo: .largeTitle)]
+                        })
+                }
+                .navigationViewStyle(.stack)
+                .talerNavBar(talerFont: talerFont)
+
+                // The side view is above (Z-Axis) the current view
+                SideBarView(stack: stack.push(),
+                            views: views,
                       currentView: $currentView,
-                   sidebarVisible: $sidebarVisible)
+                   sidebarVisible: sidebarVisible,
+                  hamburgerAction: hamburgerAction)
             }
         }
     } // Content
diff --git a/TalerWallet1/Views/Main/SideBarView.swift 
b/TalerWallet1/Views/Main/SideBarView.swift
index 31a00d9..9072542 100644
--- a/TalerWallet1/Views/Main/SideBarView.swift
+++ b/TalerWallet1/Views/Main/SideBarView.swift
@@ -15,9 +15,11 @@ struct SidebarItem {
 
 struct SideBarView: View {
     private let symLog = SymLogV(0)
+    let stack: CallStack
     let views: [SidebarItem]
     @Binding var currentView: Int
-    @Binding var sidebarVisible: Bool
+    let sidebarVisible: Bool
+    let hamburgerAction: () -> Void
     @State private var rotationEnabled = false
 
     var body: some View {
@@ -26,7 +28,7 @@ struct SideBarView: View {
                 VStack(spacing: 10) {
                     let gnuTaler = String("GNU Taler")  // this should NOT be 
translated
                     Link(gnuTaler, destination: 
URL(string:"https://taler.net";)!)
-                        .font(.largeTitle)  //.bold()     iOS 16
+                        .accessibilityFont(.largeTitle)
                         .padding(.top, 30)
                     RotatingTaler(size: 100, rotationEnabled: $rotationEnabled)
                         .onTapGesture {
@@ -35,8 +37,8 @@ struct SideBarView: View {
                     ForEach(0..<views.count, id: \.self) { i in
                         Button {
                             symLog.log("sidebar item \"\(views[i].name)\" 
selected")
-                            sidebarVisible = false      // slide sidebar to 
the left
-                            withAnimation(.easeInOut) {currentView = i}        
             // switch to the view the user selected
+                            hamburgerAction()      // slide sidebar to the left
+                            withAnimation(.easeInOut(duration: 0.3)) 
{currentView = i}        // animate to the view the user selected
                         } label: {
                             if let sysImage = views[i].sysImage {
                                 Label(views[i].name, systemImage: sysImage)
@@ -48,7 +50,7 @@ struct SideBarView: View {
                         }
                         .padding()
                         .buttonStyle(.borderless)
-                        .font(.title2)
+                        .accessibilityFont(.title2)
                         .disabled(i == currentView)
                         .accessibilityHidden(i == currentView)      // don't 
suggest the current item
                     }
@@ -68,11 +70,9 @@ struct SideBarView: View {
                 .offset(x: sidebarVisible ? sidebarWidth : 0)
                 .contentShape(Rectangle())
                 .onTapGesture {
-                    sidebarVisible = false
+                    hamburgerAction()      // slide sidebar to the left
                 }
         }
-        .animation(.linear  //(duration: SLIDEDURATION)
-                   , value: sidebarVisible)
     }
 }
 // MARK: -
@@ -86,7 +86,9 @@ fileprivate struct BindingViewContainer : View {
         ZStack(alignment: .leading) {
             views[currentView].view
                 .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: 
.center)
-            SideBarView(views: views, currentView: $currentView, 
sidebarVisible: $sidebarVisible)
+            SideBarView(stack: CallStack("Preview"), views: views, 
currentView: $currentView,
+                        sidebarVisible: sidebarVisible,
+                        hamburgerAction: { sidebarVisible = !sidebarVisible })
         }
     }
 }
diff --git a/TalerWallet1/Views/Main/WalletEmptyView.swift 
b/TalerWallet1/Views/Main/WalletEmptyView.swift
index 300248b..e8b824e 100644
--- a/TalerWallet1/Views/Main/WalletEmptyView.swift
+++ b/TalerWallet1/Views/Main/WalletEmptyView.swift
@@ -28,7 +28,7 @@ struct WalletEmptyView: View {
             }
         }
         .listStyle(myListStyle.style).anyView
-        .font(.title2)
+        .accessibilityFont(.title2)
         .background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
         .onAppear() {
             DebugViewC.shared.setViewID(VIEW_EMPTY)     // 10
diff --git a/TalerWallet1/Views/Payment/PayTemplateView.swift 
b/TalerWallet1/Views/Payment/PayTemplateView.swift
index 526d0b0..ea6c73a 100644
--- a/TalerWallet1/Views/Payment/PayTemplateView.swift
+++ b/TalerWallet1/Views/Payment/PayTemplateView.swift
@@ -10,6 +10,7 @@ import SymLog
 // both from the shop's website. We show the payment details
 struct PayTemplateView: View {
     private let symLog = SymLogV()
+    let stack: CallStack
     let navTitle = String(localized: "Confirm Payment", comment:"pay merchant")
 
     @EnvironmentObject private var controller: Controller
@@ -21,7 +22,7 @@ struct PayTemplateView: View {
     @EnvironmentObject private var model: WalletModel
 
     func acceptAction(preparePayResult: PreparePayResult) {
-        Task {
+        Task { // runs on MainActor
             do {
                 let confirmPayResult = try await 
model.confirmPayM(preparePayResult.transactionId)
                 //                symLog.log(confirmPayResult as Any)
@@ -67,6 +68,7 @@ struct PayTemplateView: View {
                     // 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,
                                      topAmount: raw, fee: nil,
                                      bottomTitle: String(localized: 
"\(currency) available:"),
@@ -76,6 +78,7 @@ struct PayTemplateView: View {
                 } else {
                     // TODO: Error - neither effective nor balanceDetails
                     Text("Error")
+                        .accessibilityFont(.body)
                 }
             }
             .listStyle(myListStyle.style).anyView
diff --git a/TalerWallet1/Views/Payment/PaymentView.swift 
b/TalerWallet1/Views/Payment/PaymentView.swift
index 6b6bc0f..b50d970 100644
--- a/TalerWallet1/Views/Payment/PaymentView.swift
+++ b/TalerWallet1/Views/Payment/PaymentView.swift
@@ -9,7 +9,8 @@ import SymLog
 // Will be called either by the user scanning a QR code or tapping the 
provided link,
 // both from the shop's website. We show the payment details
 struct PaymentView: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
     let navTitle = String(localized: "Confirm Payment", comment:"pay merchant")
 
     @EnvironmentObject private var controller: Controller
@@ -21,7 +22,7 @@ struct PaymentView: View {
     @EnvironmentObject private var model: WalletModel
 
     func acceptAction(preparePayResult: PreparePayResult) {
-        Task {
+        Task { // runs on MainActor
             do {
                 let confirmPayResult = try await 
model.confirmPayM(preparePayResult.transactionId)
 //                symLog.log(confirmPayResult as Any)
@@ -60,6 +61,7 @@ struct PaymentView: View {
                     // 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,
                                      topAmount: raw, fee: nil,
                                      bottomTitle: String(localized: 
"\(currency) available:"),
@@ -69,6 +71,7 @@ struct PaymentView: View {
                 } else {
                     // TODO: Error - neither effective nor balanceDetails
                     Text("Error")
+                        .accessibilityFont(.body)
                 }
             }
             .listStyle(myListStyle.style).anyView
@@ -152,6 +155,6 @@ struct PaymentURIView_Previews: PreviewProvider {
         )
         let url = URL(string: "taler://pay/some_amount")!
         
-        PaymentView(url: url, preparePayResult: details)
+        PaymentView(stack: CallStack("Preview"), url: url, preparePayResult: 
details)
     }
 }
diff --git a/TalerWallet1/Views/Peer2peer/PaymentPurpose.swift 
b/TalerWallet1/Views/Peer2peer/PaymentPurpose.swift
index 766aa6d..577ecc5 100644
--- a/TalerWallet1/Views/Peer2peer/PaymentPurpose.swift
+++ b/TalerWallet1/Views/Peer2peer/PaymentPurpose.swift
@@ -7,7 +7,8 @@ import taler_swift
 import SymLog
 
 struct PaymentPurpose: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
 
     let scopeInfo: ScopeInfo
     let centsToTransfer: UInt64
@@ -19,7 +20,7 @@ struct PaymentPurpose: View {
     @FocusState private var isFocused: Bool
 
     let formatter = CurrencyFormatter.shared    // TODO: based on currency
-    let buttonFont: Font = .title2
+//    let buttonFont: Font = .talerTitle2
 
     private var label: String {
         let mag = pow(10, formatter.maximumFractionDigits)
@@ -36,10 +37,10 @@ struct PaymentPurpose: View {
             VStack(alignment: .leading, spacing: 6) {
                 Text("Purpose:")
                     .padding(.top)
-                    .font(.title3)
+                    .accessibilityFont(.title3)
 
                 TextField("Purpose", text: $summary)
-                    .font(.title)
+                    .accessibilityFont(.title)
                     .foregroundColor(WalletColors().fieldForeground)     // 
text color
                     .background(WalletColors().fieldBackground)
                     .textFieldStyle(.roundedBorder)
@@ -56,7 +57,7 @@ struct PaymentPurpose: View {
                 } // maximum 100 characters
 
                 Text("Expires in:")
-                    .font(.title3)
+                    .accessibilityFont(.title3)
 
                 SelectDays(selected: $expireDays, maxExpiration: THIRTYDAYS)
                     .disabled(false)
@@ -65,12 +66,14 @@ struct PaymentPurpose: View {
                 let disabled = (expireDays == 0) || (summary.count < 1)
 
                 NavigationLink(destination: LazyView {
-                    SendDone(amountToSend: nil,
-                            amountToReceive: amount,
-                            summary: summary, expireDays: expireDays)
+                    SendDone(stack: stack.push(),
+                      amountToSend: nil,
+                   amountToReceive: amount,
+                           summary: summary,
+                        expireDays: expireDays)
                 }) {
                     Text("Request \(label) \(scopeInfo.currency)")
-                        .font(buttonFont)
+//                        .accessibilityFont(buttonFont)
                 }
                 .buttonStyle(TalerButtonStyle(type: .prominent))
                 .disabled(disabled)
diff --git a/TalerWallet1/Views/Peer2peer/RequestPayment.swift 
b/TalerWallet1/Views/Peer2peer/RequestPayment.swift
index 76da5d9..3460039 100644
--- a/TalerWallet1/Views/Peer2peer/RequestPayment.swift
+++ b/TalerWallet1/Views/Peer2peer/RequestPayment.swift
@@ -8,7 +8,8 @@ import SymLog
 
 // Called when tapping "Request Payment" in the balances list
 struct RequestPayment: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
 
     var scopeInfo: ScopeInfo
     @Binding var centsToTransfer: UInt64
@@ -40,11 +41,12 @@ struct RequestPayment: View {
                 let disabled = (centsToTransfer == 0) || someCoins.invalid || 
someCoins.tooMany
 
                 NavigationLink(destination: LazyView {
-                    PaymentPurpose(scopeInfo: scopeInfo,
-                             centsToTransfer: centsToTransfer,
-                                         fee: someCoins.fee,
-                                     summary: $summary,
-                                  expireDays: $expireDays)
+                    PaymentPurpose(stack: stack.push(),
+                               scopeInfo: scopeInfo,
+                         centsToTransfer: centsToTransfer,
+                                     fee: someCoins.fee,
+                                 summary: $summary,
+                              expireDays: $expireDays)
 //                        { deactivateAction() }
                 }) {
                     let amount = Amount.amountFromCents(currency, 
centsToTransfer)
diff --git a/TalerWallet1/Views/Peer2peer/SendAmount.swift 
b/TalerWallet1/Views/Peer2peer/SendAmount.swift
index 52c1367..a7475cd 100644
--- a/TalerWallet1/Views/Peer2peer/SendAmount.swift
+++ b/TalerWallet1/Views/Peer2peer/SendAmount.swift
@@ -8,7 +8,8 @@ import SymLog
 
 // Called when tapping "Send Coins" in the balances list
 struct SendAmount: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
 
     let amountAvailable: Amount // TODO: GetMaxPeerPushAmount
     @Binding var centsToTransfer: UInt64
@@ -44,22 +45,24 @@ struct SendAmount: View {
             VStack(alignment: .trailing) {
                 let available = amountAvailable.readableDescription
                 Text("Available: \(available)")
-                    .font(.title3)
+                    .accessibilityFont(.title3)
                     .padding(.bottom, 2)
                 CurrencyInputView(currencyField: currencyField,
                                   title: String(localized: "Amount to send:"))
                 Text("+ \(fee) payment fee")
+                    .accessibilityFont(.body)
                     .foregroundColor(.red)
                     .padding(4)
 
                 let disabled = centsToTransfer == 0    // TODO: check 
amountAvailable
 
                 NavigationLink(destination: LazyView {
-                    SendPurpose(amountAvailable: amountAvailable,
-                                centsToTransfer: centsToTransfer,
-                                            fee: fee,
-                                        summary: $summary,
-                                     expireDays: $expireDays)
+                    SendPurpose(stack: stack.push(),
+                      amountAvailable: amountAvailable,
+                      centsToTransfer: centsToTransfer,
+                                  fee: fee,
+                              summary: $summary,
+                           expireDays: $expireDays)
                 }) {
                     Text("Next")
                 }   .buttonStyle(TalerButtonStyle(type: .prominent))
@@ -102,9 +105,10 @@ struct SendAmount_Container : View {
 
     var body: some View {
         let amount = Amount(currency: LONGCURRENCY, integer: 10, fraction: 0)
-        SendAmount(amountAvailable: amount,
-                   centsToTransfer: $centsToTransfer,
-                           summary: $summary)
+        SendAmount(stack: CallStack("Preview"),
+         amountAvailable: amount,
+         centsToTransfer: $centsToTransfer,
+                 summary: $summary)
     }
 }
 
diff --git a/TalerWallet1/Views/Peer2peer/SendDone.swift 
b/TalerWallet1/Views/Peer2peer/SendDone.swift
index 0830374..5cfe04d 100644
--- a/TalerWallet1/Views/Peer2peer/SendDone.swift
+++ b/TalerWallet1/Views/Peer2peer/SendDone.swift
@@ -8,7 +8,8 @@ import SymLog
 
 // Called when initiating a P2P transaction: Send coins or Send 
Request(Invoice)
 struct SendDone: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
     let navTitle = String(localized: "P2P Ready")
 #if DEBUG
     @AppStorage("developerMode") var developerMode: Bool = true
@@ -37,15 +38,16 @@ struct SendDone: View {
 #endif
         VStack {
             if let transactionId {
-                TransactionDetailView(transactionId: transactionId,
-                                       reloadAction: reloadOneAction,
-                                           navTitle: navTitle,
-                                         doneAction: 
ViewState.shared.popToRootView,
-                                        abortAction: nil,
-                                       deleteAction: nil,
-                                         failAction: nil,
-                                      suspendAction: nil,
-                                       resumeAction: nil)
+                TransactionDetailView(stack: stack.push(),
+                              transactionId: transactionId,
+                               reloadAction: reloadOneAction,
+                                   navTitle: navTitle,
+                                 doneAction: ViewState.shared.popToRootView,
+                                abortAction: nil,
+                               deleteAction: nil,
+                                 failAction: nil,
+                              suspendAction: nil,
+                               resumeAction: nil)
                 .navigationBarBackButtonHidden(true)
                 .interactiveDismissDisabled()           // can only use "Done" 
button to dismiss
                 .navigationTitle(navTitle)
@@ -86,10 +88,11 @@ struct SendDone: View {
 struct SendNow_Previews: PreviewProvider {
     static var previews: some View {
         Group {
-            SendDone(amountToSend: try! Amount(fromString: LONGCURRENCY + 
":4.8"),
-                    amountToReceive: nil,
-                    summary: "some purpose",
-                    expireDays: 0)
+            SendDone(stack: CallStack("Preview"),
+              amountToSend: try! Amount(fromString: LONGCURRENCY + ":4.8"),
+           amountToReceive: nil,
+                   summary: "some purpose",
+                expireDays: 0)
         }
     }
 }
diff --git a/TalerWallet1/Views/Peer2peer/SendPurpose.swift 
b/TalerWallet1/Views/Peer2peer/SendPurpose.swift
index 49086df..3117450 100644
--- a/TalerWallet1/Views/Peer2peer/SendPurpose.swift
+++ b/TalerWallet1/Views/Peer2peer/SendPurpose.swift
@@ -7,7 +7,8 @@ import taler_swift
 import SymLog
 
 struct SendPurpose: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
     @FocusState private var isFocused: Bool
 
     let amountAvailable: Amount
@@ -19,8 +20,7 @@ struct SendPurpose: View {
 
     let formatter = CurrencyFormatter.shared    // TODO: based on currency
 
-    let buttonFont: Font = .title2
-    private var label: String {
+    private var value: String {
         let mag = pow(10, formatter.maximumFractionDigits)
         return formatter.string(for: Decimal(centsToTransfer) / mag) ?? ""
     }
@@ -31,15 +31,16 @@ struct SendPurpose: View {
         VStack (spacing: 6) {
             Text(amount.readableDescription)
             Text("+ \(fee) payment fee")
+                .accessibilityFont(.body)
                 .foregroundColor(.red)
             VStack(alignment: .leading, spacing: 6) {
                 Text("Purpose:")
+                    .accessibilityFont(.title2)
                     .padding(.top)
-                    .font(.title2)
 
                 if #available(iOS 16.0, *) {
                     TextField("Purpose", text: $summary, axis: .vertical)
-                        .font(.title2)
+                        .accessibilityFont(.title2)
                         .lineLimit(2...)
                         .foregroundColor(WalletColors().fieldForeground)     
// text color
                         .background(WalletColors().fieldBackground)
@@ -52,7 +53,7 @@ struct SendPurpose: View {
                         }
                 } else {
                     TextField("Purpose", text: $summary)
-                        .font(.title)
+                        .accessibilityFont(.title)
 //                        .lineLimit(2...5)   // lineLimit' is only available 
in iOS 16.0 or newer
                         .foregroundColor(WalletColors().fieldForeground)     
// text color
                         .background(WalletColors().fieldBackground)
@@ -68,10 +69,11 @@ struct SendPurpose: View {
                 HStack{
                     Spacer()
                     Text(verbatim: "\(summary.count)/100")
+                        .accessibilityFont(.body)
                 } // maximum 100 characters
 
                 Text("Expires in:")
-                    .font(.title3)
+                    .accessibilityFont(.title3)
 
                 // TODO: compute max Expiration day from peerPushCheck to 
disable 30 (and even 7)
                 SelectDays(selected: $expireDays, maxExpiration: THIRTYDAYS)
@@ -81,12 +83,13 @@ struct SendPurpose: View {
                 let disabled = (expireDays == 0) || (summary.count < 1)    // 
TODO: check amountAvailable
 
                 NavigationLink(destination: LazyView {
-                    SendDone(amountToSend: amount,
-                            amountToReceive: nil,
-                            summary: summary, expireDays: expireDays)
+                    SendDone(stack: stack.push(),
+                      amountToSend: amount,
+                   amountToReceive: nil,
+                           summary: summary,
+                        expireDays: expireDays)
                 }) {
-                    Text("Send \(label) \(amountAvailable.currencyStr) now", 
comment: "first is value, second currencyString")
-                        .font(buttonFont)
+                    Text("Send \(value) \(amountAvailable.currencyStr) now", 
comment: "first is value, second currencyString")  // TODO: currency formatter
                 }
                 .buttonStyle(TalerButtonStyle(type: .prominent))
                 .disabled(disabled)
diff --git a/TalerWallet1/Views/Settings/Pending/PendingOpView.swift 
b/TalerWallet1/Views/Settings/Pending/PendingOpView.swift
index cd68214..c3ceb29 100644
--- a/TalerWallet1/Views/Settings/Pending/PendingOpView.swift
+++ b/TalerWallet1/Views/Settings/Pending/PendingOpView.swift
@@ -13,25 +13,28 @@ struct PendingOpView: View {
 
     var body: some View {
         Section {
-            if let baseURL = pendingOp.exchangeBaseUrl {
-                Text(baseURL)
+            Group {
+                if let baseURL = pendingOp.exchangeBaseUrl {
+                    Text(baseURL)
+                }
+                Text(pendingOp.id)
+                    .accessibilityFont(.caption)
+                let isLongPolling = "isLongPolling"
+                Toggle(isLongPolling, isOn: $polling)
+                    .disabled(true)
+                let givesLifeness = "givesLifeness"
+                Toggle(givesLifeness, isOn: $liveliness)
+                    .disabled(true)
+                let isDue = "isDue"
+                Toggle(isDue, isOn: $isDue)
+                    .disabled(true)
+                let dateString = TalerDater.dateString(from: 
pendingOp.timestampDue)
+                Text(dateString)
             }
-            Text(pendingOp.id)
-                .font(.caption)
-            let isLongPolling = "isLongPolling"
-            Toggle(isLongPolling, isOn: $polling)
-                .disabled(true)
-            let givesLifeness = "givesLifeness"
-            Toggle(givesLifeness, isOn: $liveliness)
-                .disabled(true)
-            let isDue = "isDue"
-            Toggle(isDue, isOn: $isDue)
-                .disabled(true)
-            let dateString = TalerDater.dateString(from: 
pendingOp.timestampDue)
-            Text(dateString)
+            .accessibilityFont(.body)
         } header: {
             Text(pendingOp.type)
-                .font(.title2)
+                .accessibilityFont(.title2)
         }
 //        .textCase(nil)    // don't capitalize
         .onAppear {
diff --git a/TalerWallet1/Views/Settings/SettingsItem.swift 
b/TalerWallet1/Views/Settings/SettingsItem.swift
index 919ea48..e49194c 100644
--- a/TalerWallet1/Views/Settings/SettingsItem.swift
+++ b/TalerWallet1/Views/Settings/SettingsItem.swift
@@ -20,15 +20,16 @@ struct SettingsItem<Content: View>: View {
             VStack {
                 Text(name)
                     .frame(maxWidth: .infinity, alignment: .leading)
-                    .font(.talerTitle2)
+                    .accessibilityFont(.title2)
                     .padding([.bottom], 0.01)
                 if let desc = description {
                     Text(desc)
                         .frame(maxWidth: .infinity, alignment: .leading)
-                        .font(.talerCaption)
+                        .accessibilityFont(.caption)
                 }
             }
             content()
+                .accessibilityFont(.body)
         }.padding([.bottom], 4)
     }
 }
@@ -42,7 +43,7 @@ struct SettingsToggle: View {
     var body: some View {
         VStack {
             Toggle(name, isOn: $value.animation())
-                .font(.talerTitle2)
+                .accessibilityFont(.title2)
                 .onChange(of: value) { value in
                     action()
                 }
@@ -50,7 +51,7 @@ struct SettingsToggle: View {
             if let desc = description {
                 Text(desc)
                     .frame(maxWidth: .infinity, alignment: .leading)
-                    .font(.talerCaption)
+                    .accessibilityFont(.caption)
             }
         }.padding([.bottom], 4)
     }
@@ -62,7 +63,7 @@ struct SettingsFont: View {
     let action: (Int) -> Void
 
     @State private var selected = 0
-    let fonts = [String(localized: "Standard iOS Font"), 
"Atkinson-Hyperlegible", "Nunito"]
+    let fonts = [String(localized: "Standard iOS Font"), 
"Atkinson-Hyperlegible", "Nunito", "Nunito Italic"]
 
     var body: some View {
         Picker(title, selection: $selected, content: {
@@ -70,7 +71,7 @@ struct SettingsFont: View {
                 Text(fonts[index]).tag(index)
             })
         })
-            .font(.talerTitle2)
+            .accessibilityFont(.title2)
             .pickerStyle(.menu)
             .onAppear() {
                 withAnimation { selected = value }
@@ -88,12 +89,12 @@ struct SettingsStyle: View {
     var body: some View {
         HStack {
             Text(title)
-                .font(.talerTitle2)
+                .accessibilityFont(.title2)
             Spacer()
             Picker(selection: $myListStyle) {
                 ForEach(MyListStyle.allCases, id: \.self) {
                     Text($0.displayName.capitalized).tag($0)
-                        .font(.talerTitle2)
+                        .accessibilityFont(.title2)
                 }
             } label: {}
                 .pickerStyle(.menu)
@@ -119,12 +120,12 @@ struct SettingsSpeaker: View {
             let image = imageName(value)
             HStack {
                 Text(name)
-                    .font(.talerTitle2)
+                    .accessibilityFont(.title2)
                 Text(" ")
-                    .font(.talerLargeTitle)
+                    .accessibilityFont(.largeTitle)
                 Spacer()
                 Image(systemName: image.0)
-                    .font(.talerLargeTitle)
+                    .accessibilityFont(.largeTitle)
                     .accessibilityLabel(image.1)
                     .onTapGesture {
                         if value > 0 {
@@ -143,7 +144,7 @@ struct SettingsSpeaker: View {
             if let desc = description {
                 Text(desc)
                     .frame(maxWidth: .infinity, alignment: .leading)
-                    .font(.talerCaption)
+                    .accessibilityFont(.caption)
             }
         }.padding([.bottom], 4)
     }
diff --git a/TalerWallet1/Views/Settings/SettingsView.swift 
b/TalerWallet1/Views/Settings/SettingsView.swift
index 6394d07..cf2734e 100644
--- a/TalerWallet1/Views/Settings/SettingsView.swift
+++ b/TalerWallet1/Views/Settings/SettingsView.swift
@@ -21,11 +21,13 @@ struct SettingsView: View {
     private let symLog = SymLogV(0)
     let navTitle: String
 
+    @EnvironmentObject private var controller: Controller
 #if DEBUG
     @AppStorage("developerMode") var developerMode: Bool = true
 #else
     @AppStorage("developerMode") var developerMode: Bool = false
 #endif
+    @AppStorage("useHaptics") var useHaptics: Bool = false
     @AppStorage("playSounds") var playSounds: Int = 0
     @AppStorage("talerFont") var talerFont: Int = 0
     @AppStorage("developDelay") var developDelay: Bool = false
@@ -55,7 +57,7 @@ struct SettingsView: View {
         Button("Reset", role: .destructive) {
             didReset = true
             showResetAlert = false
-            Task {
+            Task { // runs on MainActor
                 symLog.log("❗️Reset wallet-core❗️")
                 do {
                     try await model.resetWalletCoreT()
@@ -81,8 +83,12 @@ struct SettingsView: View {
         let walletCore = WalletCore.shared
         Group {
             List {
+                if controller.hapticCapability.supportsHaptics {
+                    SettingsToggle(name: String(localized: "Haptics"), value: 
$useHaptics,
+                                   description: String(localized: "Vibration 
Feedback"))
+                }
                 SettingsSpeaker(name: String(localized: "Play Payment 
Sounds"), value: $playSounds,
-                                description: String(localized: "After a 
transaction finished"))
+                                description: String(localized: "When a 
transaction finished"))
                 SettingsFont(title: String(localized: "Font:"), value: 
talerFont, action: redraw)
                 SettingsStyle(title: String(localized: "Liststyle:"), 
myListStyle: $myListStyle)
                 if diagnosticModeEnabled {
@@ -98,17 +104,15 @@ struct SettingsView: View {
                             SettingsItem(name: String(localized: "Pending 
Operations"),
                                   description: String(localized: "Exchange not 
yet ready...")) {}
                         }
-                        SettingsToggle(name: String(localized: "Set 2 seconds 
delay"), value: $developDelay,
+                        SettingsToggle(name: String(localized: "Set 2 seconds 
delay"),
+                                      value: $developDelay.onChange({ delay in
+                                        walletCore.developDelay = delay}),
                                 description: String(localized: "After each 
wallet-core action"))
-                        .onChange(of: developDelay, perform: { developDelay in
-                            walletCore.developDelay = developDelay
-                        })
-
                         SettingsItem(name: String(localized: "Withdraw 
\(DEMOCURRENCY)"),
                               description: String(localized: "Get money for 
testing")) {
                             Button("Withdraw") {
                                 withDrawDisabled = true    // don't run twice
-                                Task {
+                                Task { // runs on MainActor
                                     symLog.log("Withdraw KUDOS")
                                     do {
                                         try await model.loadTestKudosM(test: 
false)
@@ -124,7 +128,7 @@ struct SettingsView: View {
                               description: String(localized: "Get money for 
testing")) {
                             Button("Withdraw") {
                                 withDrawDisabled = true    // don't run twice
-                                Task {
+                                Task { // runs on MainActor
                                     symLog.log("Withdraw TESTKUDOS")
                                     do {
                                         try await model.loadTestKudosM(test: 
true)
@@ -140,7 +144,7 @@ struct SettingsView: View {
                               description: String(localized: "Perform basic 
test transactions")) {
                             Button("Demo 1") {
                                 checkDisabled = true    // don't run twice
-                                Task {
+                                Task { // runs on MainActor
                                     symLog.log("running integration test on 
demo")
                                     do {
                                         try await 
model.runIntegrationTestM(newVersion: false, test: false)
@@ -156,7 +160,7 @@ struct SettingsView: View {
                               description: String(localized: "Perform basic 
test transactions")) {
                             Button("Test 1") {
                                 checkDisabled = true    // don't run twice
-                                Task {
+                                Task { // runs on MainActor
                                     symLog.log("running integration test on 
test")
                                     do {
                                         try await 
model.runIntegrationTestM(newVersion: false, test: true)
@@ -172,7 +176,7 @@ struct SettingsView: View {
                               description: String(localized: "Perform more 
test transactions")) {
                             Button("Demo 2") {
                                 checkDisabled = true    // don't run twice
-                                Task {
+                                Task { // runs on MainActor
                                     symLog.log("running integration test V2 on 
demo")
                                     do {
                                         try await 
model.runIntegrationTestM(newVersion: true, test: false)
@@ -188,7 +192,7 @@ struct SettingsView: View {
                               description: String(localized: "Perform more 
test transactions")) {
                             Button("Test 2") {
                                 checkDisabled = true    // don't run twice
-                                Task {
+                                Task { // runs on MainActor
                                     symLog.log("running integration test V2 on 
test")
                                     do {
                                         try await 
model.runIntegrationTestM(newVersion: true, test: true)
diff --git a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pAcceptDone.swift 
b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pAcceptDone.swift
index b3941ea..b26a6d0 100644
--- a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pAcceptDone.swift
+++ b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pAcceptDone.swift
@@ -8,7 +8,8 @@ import SymLog
 
 // Called when accepting a scanned P2P transaction: Receive coins or Pay 
Request(Invoice)
 struct P2pAcceptDone: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
 
     let transactionId: String
     let incoming: Bool
@@ -29,15 +30,16 @@ struct P2pAcceptDone: View {
 #endif
         let navTitle = incoming ? String(localized: "Received P2P", comment: 
"Title, short")
                                 : String(localized: "Paid P2P", comment: 
"Title, short")
-        TransactionDetailView(transactionId: transactionId,
-                               reloadAction: reloadOneAction,
-                                   navTitle: navTitle,
-                                 doneAction: { dismissTop() },
-                                abortAction: nil,
-                               deleteAction: nil,
-                                 failAction: nil,
-                              suspendAction: nil,
-                               resumeAction: nil)
+        TransactionDetailView(stack: stack.push(),
+                      transactionId: transactionId,
+                       reloadAction: reloadOneAction,
+                           navTitle: navTitle,
+                         doneAction: { dismissTop() },
+                        abortAction: nil,
+                       deleteAction: nil,
+                         failAction: nil,
+                      suspendAction: nil,
+                       resumeAction: nil)
             .navigationBarBackButtonHidden(true)
             .interactiveDismissDisabled()           // can only use "Done" 
button to dismiss
             .navigationTitle(navTitle)
@@ -64,6 +66,8 @@ struct P2pAcceptDone: View {
 // MARK: -
 struct P2pAcceptDone_Previews: PreviewProvider {
     static var previews: some View {
-        P2pAcceptDone(transactionId: "some ID", incoming: true)
+        P2pAcceptDone(stack: CallStack("Preview"),
+              transactionId: "some ID",
+                   incoming: true)
     }
 }
diff --git a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift 
b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift
index cdcb99a..01529fe 100644
--- a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift
+++ b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift
@@ -9,7 +9,8 @@ import SymLog
 // Called either when scanning a QR code or tapping the provided link
 // from another user's Send Request(Invoice). We show the P2P details.
 struct P2pPayURIView: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
     let navTitle = String(localized: "Pay P2P")
 
     // the scanned URL
@@ -39,8 +40,9 @@ struct P2pPayURIView: View {
                 .navigationTitle(navTitle)
 
                 NavigationLink(destination: LazyView {
-                        P2pAcceptDone(transactionId: 
peerPullDebitResponse.transactionId,
-                                           incoming: false)
+                    P2pAcceptDone(stack: stack.push(),
+                          transactionId: peerPullDebitResponse.transactionId,
+                               incoming: false)
                     }) {
                         Text("Confirm Payment", comment:"pay P2P 
request/invoice")      // SHEET_PAY_P2P
                     }.buttonStyle(TalerButtonStyle(type: .prominent))
diff --git a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift 
b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift
index d38d73b..9760a2b 100644
--- a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift
+++ b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift
@@ -9,7 +9,8 @@ import SymLog
 // Will be called either by the user scanning a QR code or tapping the 
provided link,
 // from another user's SendCoins. We show the P2P details - but first the ToS 
must be accepted.
 struct P2pReceiveURIView: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
     let navTitle = String(localized: "P2P Receive")
     @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
 
@@ -40,24 +41,17 @@ struct P2pReceiveURIView: View {
                 let tosAccepted = true  // TODO: 
https://bugs.gnunet.org/view.php?id=7869
                 if tosAccepted {
                     NavigationLink(destination: LazyView {
-                        P2pAcceptDone(transactionId: 
peerPushCreditResponse.transactionId,
-                                           incoming: true)
+                        P2pAcceptDone(stack: stack.push(),
+                              transactionId: 
peerPushCreditResponse.transactionId,
+                                   incoming: true)
                     }) {
                         Text("Accept P2P Receive")      // SHEET_RCV_P2P_ACCEPT
                     }.buttonStyle(TalerButtonStyle(type: .prominent))
                         .padding()
                 } else {
-                    Text("You must accept the Terms of Service first before 
you can receive electronic cash to your wallet.")
-                        .multilineTextAlignment(.leading)
-                        .padding()
-                    NavigationLink(destination: LazyView {
-                        WithdrawTOSView(exchangeBaseUrl: nil,
-                                                 viewID: SHEET_RCV_P2P_TOS,
-                                           acceptAction: nil)         // pop 
back to here
-                    }) {
-                        Text("Read Terms of Service")
-                    }.buttonStyle(TalerButtonStyle(type: .prominent))
-                        .padding()
+                    ToSButtonView(exchangeBaseUrl: nil,
+                                           viewID: SHEET_RCV_P2P_TOS,
+                                              p2p: true)
                 }
             } else {
                 // Yikes no details or no baseURL
diff --git a/TalerWallet1/Views/Sheets/QRSheet.swift 
b/TalerWallet1/Views/Sheets/QRSheet.swift
index 6385ec4..315c60b 100644
--- a/TalerWallet1/Views/Sheets/QRSheet.swift
+++ b/TalerWallet1/Views/Sheets/QRSheet.swift
@@ -8,7 +8,8 @@ import SymLog
 import AVFoundation
 
 struct QRSheet: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
     @State private var scannedCode: String?
 
     var body: some View {
@@ -19,7 +20,7 @@ struct QRSheet: View {
                 if let scannedURL = URL(string: scannedCode!) {
                     let scheme = scannedURL.scheme
                     if scheme == "taler" {
-                        URLSheet(urlToOpen: scannedURL)
+                        URLSheet(stack: stack.push(), urlToOpen: scannedURL)
                     } else {
                         let _ = print(scannedURL)       // TODO: logging
                         ErrorView(errortext: scannedURL.absoluteString)
diff --git a/TalerWallet1/Views/Sheets/ShareSheet.swift 
b/TalerWallet1/Views/Sheets/ShareSheet.swift
index e56148f..72a6faa 100644
--- a/TalerWallet1/Views/Sheets/ShareSheet.swift
+++ b/TalerWallet1/Views/Sheets/ShareSheet.swift
@@ -21,7 +21,7 @@ import SymLog
 public class ShareSheet: ObservableObject {
     private let symLog = SymLogC()
 
-    static func shareSheet(url: String) {
+    @MainActor static func shareSheet(url: String) {
         let url = URL(string: url)
         let activityView = UIActivityViewController(activityItems: [url!], 
applicationActivities: nil)
 
diff --git a/TalerWallet1/Views/Sheets/Sheet.swift 
b/TalerWallet1/Views/Sheets/Sheet.swift
index abc564b..1daa1e6 100644
--- a/TalerWallet1/Views/Sheets/Sheet.swift
+++ b/TalerWallet1/Views/Sheets/Sheet.swift
@@ -7,9 +7,10 @@ import SymLog
 import os.log
 
 struct Sheet: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
     @Environment(\.dismiss) var dismiss     // call dismiss() to get rid of 
the sheet
     @EnvironmentObject private var debugViewC: DebugViewC
+    @AppStorage("talerFont") var talerFont: Int = 0
 
     var sheetView: AnyView
 
@@ -30,12 +31,14 @@ struct Sheet: View {
                 .navigationBarItems(leading: cancelButton)
                 .navigationBarTitleDisplayMode(.automatic)
                 
.background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
-        }.navigationViewStyle(.stack)
+        }
+        .navigationViewStyle(.stack)
+        .talerNavBar(talerFont: talerFont)
         .overlay(alignment: .top) {
             // Show the viewID on top of the sheet's NavigationView
             Text(idString)
-                .font(.caption2)
                 .foregroundColor(.purple)
+                .font(.system(size: 11))        // no accessibilityFont
                 .monospacedDigit()
                 .edgesIgnoringSafeArea(.top)
                 .id("sheetID")
diff --git a/TalerWallet1/Views/Sheets/URLSheet.swift 
b/TalerWallet1/Views/Sheets/URLSheet.swift
index 1db6169..b9f5751 100644
--- a/TalerWallet1/Views/Sheets/URLSheet.swift
+++ b/TalerWallet1/Views/Sheets/URLSheet.swift
@@ -6,7 +6,8 @@ import SwiftUI
 import SymLog
 
 struct URLSheet: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
     let navTitle = String(localized: "Checking Link")
     var urlToOpen: URL
     @EnvironmentObject private var controller: Controller
@@ -17,21 +18,21 @@ struct URLSheet: View {
         Group {
             switch urlCommand {
                 case .withdraw:
-                    WithdrawURIView(url: urlToOpen)
+                    WithdrawURIView(stack: stack.push(), url: urlToOpen)
                 case .pay:
-                    PaymentView(url: urlToOpen)
+                    PaymentView(stack: stack.push(), url: urlToOpen)
                 case .payPull:
-                    P2pPayURIView(url: urlToOpen)
+                    P2pPayURIView(stack: stack.push(), url: urlToOpen)
                 case .payPush:
-                    P2pReceiveURIView(url: urlToOpen)
+                    P2pReceiveURIView(stack: stack.push(), url: urlToOpen)
                 case .payTemplate:
-                    PayTemplateView(url: urlToOpen)
+                    PayTemplateView(stack: stack.push(), url: urlToOpen)
 //                case .reward:
 //                    RewardURIView(url: urlToOpen)
                 default:        // Error view
                     VStack {
                         Text("unknown command")
-                            .font(.title)
+                            .accessibilityFont(.title)
                         Text(controller.messageForSheet ?? 
urlToOpen.absoluteString)
                     }
                     .navigationTitle(navTitle)
diff --git a/TalerWallet1/Views/Transactions/ManualDetails.swift 
b/TalerWallet1/Views/Transactions/ManualDetails.swift
index 8172254..adc9e15 100644
--- a/TalerWallet1/Views/Transactions/ManualDetails.swift
+++ b/TalerWallet1/Views/Transactions/ManualDetails.swift
@@ -14,50 +14,53 @@ struct ManualDetails: View {
             let payURL = URL(string: payto)
             let iban = payURL?.iban ?? "unknown IBAN"
             let amount = common.amountRaw.readableDescription
-            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)
-            HStack {
-                Text(details.reservePub)
-                    .monospacedDigit()
-                    .accessibilityLabel("Cryptocode")
-                Spacer()
-                CopyButton(textToCopy: details.reservePub, vertical: true)
-                    .accessibilityLabel("Copy the cryptocode")
-                    .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:")
-                .multilineTextAlignment(.leading)
-                .listRowSeparator(.hidden)
-            HStack {
-                Text(iban)
-                    .monospacedDigit()
-                Spacer()
-                CopyButton(textToCopy: iban, vertical: true)
-                    .accessibilityLabel("Copy the IBAN")
-                    .disabled(false)
-            }   .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.")
-                .multilineTextAlignment(.leading)
-                .listRowSeparator(.visible)
-            Text("Alternative: If your bank already supports PayTo, you can 
use this PayTo-Link instead:")
-                .multilineTextAlignment(.leading)
-                .padding(.top, 2)
-                .listRowSeparator(.hidden)
-            HStack {
-                Text(verbatim: "|")       // only reason for this 
leading-aligned text is to get a nice full length listRowSeparator
-                    .accessibilityHidden(true)
-                    .foregroundColor(Color.clear)
-                Spacer()
-                ShareButton(textToShare: payto)
-                    .accessibilityLabel("Share the PayTo URL")
-                    .disabled(false)
-                Spacer()
-            }   .listRowSeparator(.automatic)
+            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)
+                HStack {
+                    Text(details.reservePub)
+                        .monospacedDigit()
+                        .accessibilityLabel("Cryptocode")
+                    Spacer()
+                    CopyButton(textToCopy: details.reservePub, vertical: true)
+                        .accessibilityLabel("Copy the cryptocode")
+                        .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:")
+                    .multilineTextAlignment(.leading)
+                    .listRowSeparator(.hidden)
+                HStack {
+                    Text(iban)
+                        .monospacedDigit()
+                    Spacer()
+                    CopyButton(textToCopy: iban, vertical: true)
+                        .accessibilityLabel("Copy the IBAN")
+                        .disabled(false)
+                }   .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.")
+                    .multilineTextAlignment(.leading)
+                    .listRowSeparator(.visible)
+                Text("Alternative: If your bank already supports PayTo, you 
can use this PayTo-Link instead:")
+                    .multilineTextAlignment(.leading)
+                    .padding(.top, 2)
+                    .listRowSeparator(.hidden)
+                HStack {
+                    Text(verbatim: "|")       // only reason for this 
leading-aligned text is to get a nice full length listRowSeparator
+                        .accessibilityHidden(true)
+                        .foregroundColor(Color.clear)
+                    Spacer()
+                    ShareButton(textToShare: payto)
+                        .accessibilityLabel("Share the PayTo URL")
+                        .disabled(false)
+                    Spacer()
+                }   .listRowSeparator(.automatic)
+            }
+                .accessibilityFont(.body)
         }
     }
 }
diff --git a/TalerWallet1/Views/Transactions/ThreeAmounts.swift 
b/TalerWallet1/Views/Transactions/ThreeAmounts.swift
index 7b1397b..ff01a1a 100644
--- a/TalerWallet1/Views/Transactions/ThreeAmounts.swift
+++ b/TalerWallet1/Views/Transactions/ThreeAmounts.swift
@@ -68,12 +68,12 @@ struct ThreeAmountsView: View {
                 VStack(alignment: .leading) {
                     Text("Using Exchange:")
                         .multilineTextAlignment(.leading)
-                        .font(.body)
+                        .accessibilityFont(.body)
                     HStack {
                         Spacer()
                         Text(baseURL.trimURL())
                             .multilineTextAlignment(.center)
-                            .font(large ? .title2 : .title3)
+                            .accessibilityFont(large ? .title2 : .title3)
 //                          .fontWeight(large ? .medium : .regular)  // 
@available(iOS 16.0, *)
                             .foregroundColor(labelColor)
                         Spacer()
diff --git a/TalerWallet1/Views/Transactions/TransactionDetailView.swift 
b/TalerWallet1/Views/Transactions/TransactionDetailView.swift
index 3178519..148d755 100644
--- a/TalerWallet1/Views/Transactions/TransactionDetailView.swift
+++ b/TalerWallet1/Views/Transactions/TransactionDetailView.swift
@@ -22,7 +22,8 @@ extension Transaction {             // for Dummys
 }
 // MARK: -
 struct TransactionDetailView: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
     @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
 #if DEBUG
     @AppStorage("developerMode") var developerMode: Bool = true
@@ -66,17 +67,16 @@ struct TransactionDetailView: View {
                     } }
                 } // Suspend + Resume buttons
                 Text(dateString)
-                    .font(.title2)
+                    .accessibilityFont(.title2)
                     .listRowSeparator(.hidden)
                 HStack {
                     Text(verbatim: "|")   // only reason for this 
leading-aligned text is to get a nice full length listRowSeparator
-                        .font(.title2)
                         .accessibilityHidden(true)
                         .foregroundColor(Color.clear)
                     Spacer()
                     Text("Status: \(common.txState.major.localizedState)")
-                        .font(.title2)
                 }    .listRowSeparator(.automatic)
+                    .accessibilityFont(.title2)
                 SwitchCase(transaction: $transaction, hasDone: doneAction != 
nil)
 
                 if transaction.isAbortable { if let abortAction {
@@ -128,7 +128,7 @@ struct TransactionDetailView: View {
                         } else {
                             symLog.log("ignoring newTxState.major: 
\(newMajor)")
                         }
-                    } else { Task {
+                    } else { Task { // runs on MainActor
                         do {
                             symLog.log("newState: \(newMajor), reloading 
transaction")
                             withAnimation() { transaction = 
Transaction(dummyCurrency: DEMOCURRENCY); viewId = UUID() }
@@ -175,8 +175,9 @@ struct TransactionDetailView: View {
             let pending = transaction.isPending
             Group {
                 switch transaction {
-                    case .dummy(let dummyTransaction):
+                    case .dummy(_):
                         Text("")
+                            .accessibilityFont(.body)
                     case .withdrawal(let withdrawalTransaction):
                         let details = withdrawalTransaction.details
                         if pending {
@@ -209,7 +210,7 @@ struct TransactionDetailView: View {
                     case .payment(let paymentTransaction):
                         let details = paymentTransaction.details
                         Text(details.info.summary)
-                            .font(.title2)
+                            .accessibilityFont(.title2)
                             .lineLimit(4)
                             .padding(.bottom)
                         ThreeAmountsSheet(common: common, topTitle: 
String(localized: "Sum to be paid:"),
@@ -229,16 +230,16 @@ struct TransactionDetailView: View {
                     case .peer2peer(let p2pTransaction):
                         let details = p2pTransaction.details                   
 // TODO: details
                         Text(details.info.summary)
-                            .font(.title2)
+                            .accessibilityFont(.title2)
                             .lineLimit(4)
                             .padding(.bottom)
-                        // TODO: isSendCoins should show QR only while not 
expired
+                        // TODO: isSendCoins should show QR only while not yet 
expired  - either set timer or wallet-core should do so and send a 
state-changed notification
                         if pending {
                             QRCodeDetails(transaction: transaction)
                             if hasDone {
                                 Text("QR code and link can also be scanned or 
copied / shared from Transactions later.")
                                     .multilineTextAlignment(.leading)
-                                    .font(.subheadline)
+                                    .accessibilityFont(.subheadline)
                                     .padding(.top)
                             }
                         }
@@ -265,7 +266,7 @@ struct TransactionDetailView: View {
             } else if keys.contains(EXCHANGEBASEURL) {
                 if let baseURL = details[EXCHANGEBASEURL] {
                     Text("from \(baseURL.trimURL())") 
-                        .font(.title2)
+                        .accessibilityFont(.title2)
                         .padding(.bottom)
                 }
             }
diff --git a/TalerWallet1/Views/Transactions/TransactionRowView.swift 
b/TalerWallet1/Views/Transactions/TransactionRowView.swift
index cf57414..ee8ff88 100644
--- a/TalerWallet1/Views/Transactions/TransactionRowView.swift
+++ b/TalerWallet1/Views/Transactions/TransactionRowView.swift
@@ -12,11 +12,11 @@ struct TransactionRowCenter: View {
     var body: some View {
         VStack(alignment: .leading) {
             Text(centerTop)
-                .font(.headline)
-                .fontWeight(.medium)
+                .accessibilityFont(.headline)
+//                .fontWeight(.medium)      iOS 16
                 .padding(.bottom, -2.0)
             Text(centerBottom)
-                .font(.callout)
+                .accessibilityFont(.callout)
         }
     }
 }
@@ -41,7 +41,7 @@ struct TransactionRowView: View {
         HStack(spacing: 6) {
             Image(systemName: incoming ? "text.badge.plus" : 
"text.badge.minus")
                 .foregroundColor(foreColor)
-                .font(.largeTitle)
+                .accessibilityFont(.largeTitle)
                 .accessibility(hidden: true)
 
             TransactionRowCenter(centerTop: transaction.localizedType,
@@ -51,8 +51,8 @@ struct TransactionRowView: View {
                 let sign = incoming ? "+" : "-"
                 let valueStr = sign + amount.valueStr
                 Text(valueStr)
-                    .font(.title)
                     .foregroundColor(foreColor)
+                    .accessibilityFont(.title)
                     .monospacedDigit()
             }
         }
diff --git a/TalerWallet1/Views/Transactions/TransactionsEmptyView.swift 
b/TalerWallet1/Views/Transactions/TransactionsEmptyView.swift
index fa382ba..73dc463 100644
--- a/TalerWallet1/Views/Transactions/TransactionsEmptyView.swift
+++ b/TalerWallet1/Views/Transactions/TransactionsEmptyView.swift
@@ -9,7 +9,7 @@ import SymLog
 /// It is the very first thing the user sees after installing the app
 
 struct TransactionsEmptyView: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
     @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
 
     let currency: String
@@ -19,7 +19,7 @@ struct TransactionsEmptyView: View {
             Section {
                 Text("There are no transactions for \(currency).")
             }
-            .font(.title2)
+            .accessibilityFont(.title2)
         }
         .listStyle(myListStyle.style).anyView
 //        .padding(.vertical)
diff --git a/TalerWallet1/Views/Transactions/TransactionsListView.swift 
b/TalerWallet1/Views/Transactions/TransactionsListView.swift
index 16ce785..a0865a3 100644
--- a/TalerWallet1/Views/Transactions/TransactionsListView.swift
+++ b/TalerWallet1/Views/Transactions/TransactionsListView.swift
@@ -7,6 +7,7 @@ import SymLog
 
 struct TransactionsListView: View {
     private let symLog = SymLogV(0)
+    let stack: CallStack
     @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
     let navTitle: String
 
@@ -28,6 +29,7 @@ struct TransactionsListView: View {
         ScrollViewReader { scrollView in
             List {
                 TransactionsRowsView(symLog: symLog,
+                                      stack: stack.push(),
                                    currency: currency,
                                transactions: transactions,
 //                          reloadAllAction: reloadAllAction,
@@ -78,6 +80,7 @@ struct TransactionsListView: View {
 // used by TransactionsListView, and by Balances to show the last 3 
transactions
 struct TransactionsRowsView: View {
     let symLog: SymLogV?
+    let stack: CallStack
     let currency: String
     let transactions: [Transaction]
 //  let reloadAllAction: () async -> ()
@@ -97,15 +100,16 @@ struct TransactionsRowsView: View {
         ForEach(Array(zip(transactions.indices, transactions)), id: \.1) { 
index, transaction in
             NavigationLink {
                 LazyView {
-                    TransactionDetailView(transactionId: transaction.id,
-                                           reloadAction: reloadOneAction,
-                                               navTitle: nil,
-                                             doneAction: nil,
-                                            abortAction: abortAction,
-                                           deleteAction: deleteAction,
-                                             failAction: failAction,
-                                          suspendAction: suspendAction,
-                                           resumeAction: resumeAction)
+                    TransactionDetailView(stack: stack.push(),
+                                  transactionId: transaction.id,
+                                   reloadAction: reloadOneAction,
+                                       navTitle: nil,
+                                     doneAction: nil,
+                                    abortAction: abortAction,
+                                   deleteAction: deleteAction,
+                                     failAction: failAction,
+                                  suspendAction: suspendAction,
+                                   resumeAction: resumeAction)
                 }
             } label: {
                 TransactionRowView(transaction: transaction)
diff --git a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptDone.swift 
b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptDone.swift
index ec64275..0799c6c 100644
--- a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptDone.swift
+++ b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptDone.swift
@@ -7,7 +7,8 @@ import taler_swift
 import SymLog
 
 struct WithdrawAcceptDone: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
     let navTitle = String(localized: "Confirm with Bank")
 
     let exchangeBaseUrl: String?
@@ -29,15 +30,16 @@ struct WithdrawAcceptDone: View {
 #endif
         Group {
             if let transactionId {
-                TransactionDetailView(transactionId: transactionId,
-                                       reloadAction: reloadOneAction,
-                                           navTitle: navTitle,
-                                         doneAction: { dismissTop() },
-                                        abortAction: nil,
-                                       deleteAction: nil,
-                                         failAction: nil,
-                                      suspendAction: nil,
-                                       resumeAction: nil)
+                TransactionDetailView(stack: stack.push(),
+                              transactionId: transactionId,
+                               reloadAction: reloadOneAction,
+                                   navTitle: navTitle,
+                                 doneAction: { dismissTop() },
+                                abortAction: nil,
+                               deleteAction: nil,
+                                 failAction: nil,
+                              suspendAction: nil,
+                               resumeAction: nil)
                 .navigationBarBackButtonHidden(true)
                 .interactiveDismissDisabled()           // can only use "Done" 
button to dismiss
                 .navigationTitle(navTitle)
@@ -66,7 +68,8 @@ struct WithdrawAcceptDone: View {
 // MARK: -
 struct WithdrawAcceptDone_Previews: PreviewProvider {
     static var previews: some View {
-        WithdrawAcceptDone(exchangeBaseUrl: DEMOEXCHANGE,
-                           url: URL(string: DEMOSHOP)!)
+        WithdrawAcceptDone(stack: CallStack("Preview"),
+                 exchangeBaseUrl: DEMOEXCHANGE,
+                             url: URL(string: DEMOSHOP)!)
     }
 }
diff --git a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptView.swift 
b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptView.swift
index ada134f..d336c82 100644
--- a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptView.swift
+++ b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptView.swift
@@ -7,7 +7,7 @@ import taler_swift
 import SymLog
 
 struct WithdrawAcceptView: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
     let navTitle = String(localized: "Accept Withdrawal")
 
     let exchangeBaseUrl: String
diff --git 
a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawProgressView.swift 
b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawProgressView.swift
index f623c3a..0c7e906 100644
--- a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawProgressView.swift
+++ b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawProgressView.swift
@@ -15,7 +15,7 @@ struct WithdrawProgressView: View {
             HStack {
                 Spacer()
                 Text(message)
-                    .font(.title)
+                    .accessibilityFont(.title)
                 Spacer()
             }
             Spacer()
diff --git a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawTOSView.swift 
b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawTOSView.swift
index 41b7839..3df21c8 100644
--- a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawTOSView.swift
+++ b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawTOSView.swift
@@ -6,12 +6,12 @@ import SwiftUI
 import SymLog
 
 struct WithdrawTOSView: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
     @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
 
     let navTitle = String(localized: "Terms of Service")
 
-    var exchangeBaseUrl: String?
+    let exchangeBaseUrl: String?
 
     @EnvironmentObject private var model: WalletModel
 
@@ -24,7 +24,7 @@ struct WithdrawTOSView: View {
     var body: some View {
         VStack {
             Content(symLog: symLog, exchangeTOS: exchangeTOS, myListStyle: 
$myListStyle) {
-                Task {
+                Task { // runs on MainActor
                     do {
                         if let exchangeBaseUrl {
                             _ = try await 
model.setExchangeTOSAcceptedM(exchangeBaseUrl, etag: exchangeTOS!.currentEtag)
@@ -95,17 +95,18 @@ extension WithdrawTOSView {
                         if #available(iOS 16.0, *) {
                             Section {
                                 Text(term5)
-                                    .font(.footnote)
+                                    .accessibilityFont(.footnote)
                                     .foregroundColor(Color(UIColor.label))
                             }
                         } else {
                             Text(term5)
-                                .font(.footnote)
+                                .accessibilityFont(.footnote)
                                 .foregroundColor(Color(UIColor.label))
                         }
-                    } else {
+                    } else {        // MarkDown
                         Section {
                             Text(term0)
+                                .accessibilityFont(.body)
                         }
                     }
                 }.safeAreaInset(edge: .bottom) {
diff --git a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawURIView.swift 
b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawURIView.swift
index c41d20c..8e7580e 100644
--- a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawURIView.swift
+++ b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawURIView.swift
@@ -10,7 +10,8 @@ import SymLog
 // We show the user the withdrawal details - but first the ToS must be 
accepted.
 // After the user confirmed the withdrawal, we show a button to return to the 
bank website to confirm there, too
 struct WithdrawURIView: View {
-    private let symLog = SymLogV()
+    private let symLog = SymLogV(0)
+    let stack: CallStack
     let navTitle = String(localized: "Withdrawal")
 
     // the URL from the bank website
@@ -50,23 +51,17 @@ struct WithdrawURIView: View {
                 let tosAccepted = withdrawalAmountDetails.tosAccepted
                 if tosAccepted {
                     NavigationLink(destination: LazyView {
-                        WithdrawAcceptDone(exchangeBaseUrl: exchangeBaseUrl, 
url: url)
+                        WithdrawAcceptDone(stack: stack.push(),
+                                 exchangeBaseUrl: exchangeBaseUrl,
+                                             url: url)
                     }) {
                         Text("Confirm Withdrawal")      // 
SHEET_WITHDRAW_ACCEPT
                     }.buttonStyle(TalerButtonStyle(type: .prominent))
                         .padding()
                 } else {
-                    Text("You must accept the Exchange's Terms of Service 
first before you can use it to withdraw electronic cash to your wallet.")
-                        .multilineTextAlignment(.leading)
-                        .padding()
-                    NavigationLink(destination: LazyView {
-                        WithdrawTOSView(exchangeBaseUrl: exchangeBaseUrl,
-                                                 viewID: SHEET_WITHDRAW_TOS,
-                                           acceptAction: nil)         // pop 
back to here
-                    }) {
-                        Text("Read Terms of Service")  // VIEW_WITHDRAW_TOS
-                    }.buttonStyle(TalerButtonStyle(type: .prominent))
-                        .padding()
+                    ToSButtonView(exchangeBaseUrl: exchangeBaseUrl,
+                                           viewID: SHEET_WITHDRAW_TOS,
+                                              p2p: false)
                 }
             } else {
                 // Yikes no details or no baseURL
diff --git a/Taler_Wallet Info.plist b/Taler_Wallet Info.plist
index 958c7e9..811f070 100644
--- a/Taler_Wallet Info.plist   
+++ b/Taler_Wallet Info.plist   
@@ -32,6 +32,8 @@
                <string>Atkinson-Hyperlegible-Italic-102.otf</string>
                <string>Nunito-Regular.ttf</string>
                <string>Nunito-Bold.ttf</string>
+               <string>Nunito-Black.ttf</string>
+               <string>Nunito-BlackItalic.ttf</string>
                <string>Nunito-BoldItalic.ttf</string>
                <string>Nunito-Italic.ttf</string>
        </array>
diff --git a/taler-swift/Sources/taler-swift/Amount.swift 
b/taler-swift/Sources/taler-swift/Amount.swift
index 647055b..2e91e6c 100644
--- a/taler-swift/Sources/taler-swift/Amount.swift
+++ b/taler-swift/Sources/taler-swift/Amount.swift
@@ -38,15 +38,15 @@ enum AmountError: Error {
     case divideByZero
 }
 
-public struct ScopedCurrencyInfo: Codable {
-    var decimalSeparator: String
-    var numFractionalDigits: Int        // 0 Yen, 2 €,$, 3 arabic
-    var numTinyDigits: Int              // SuperScriptDigits
-    var isCurrencyNameLeading: Bool
+public struct ScopedCurrencyInfo: Codable, Sendable {
+    let decimalSeparator: String
+    let numFractionalDigits: Int        // 0 Yen, 2 €,$, 3 arabic
+    let numTinyDigits: Int              // SuperScriptDigits
+    let isCurrencyNameLeading: Bool
 }
 
 /// A value of some currency.
-public class Amount: Codable, Hashable, CustomStringConvertible {
+public final class Amount: Codable, Hashable, @unchecked Sendable, 
CustomStringConvertible {        // TODO: @unchecked
     /// Format that a currency must match.
     private static let currencyRegex = #"^[-_*A-Za-z0-9]{1,12}$"#
     
diff --git a/taler-swift/Sources/taler-swift/Time.swift 
b/taler-swift/Sources/taler-swift/Time.swift
index 43ada5d..98f0e27 100644
--- a/taler-swift/Sources/taler-swift/Time.swift
+++ b/taler-swift/Sources/taler-swift/Time.swift
@@ -17,7 +17,7 @@ enum TimestampError: Error {
 }
 
 /// A point in time, represented by milliseconds from January 1, 1970..
-public enum Timestamp: Codable, Hashable {
+public enum Timestamp: Codable, Hashable, Sendable {
     case milliseconds(UInt64)
     case never
     

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