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