[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-taler-ios] branch master updated (ad57348 -> dbf44d6)
From: |
gnunet |
Subject: |
[taler-taler-ios] branch master updated (ad57348 -> dbf44d6) |
Date: |
Thu, 27 Jul 2023 09:09:33 +0200 |
This is an automated email from the git hooks/post-receive script.
marc-stibane pushed a change to branch master
in repository taler-ios.
from ad57348 iOS: bump version to 0.9.3 (14)
new fbe5f9a Test notes
new f2bc812 navigationBarTitleDisplayMode
new 134c582 logging
new d8b2c28 Settings: Reset wallet
new 407d4a7 insufficientBalance
new 4a8e217 no need to call urlCommand async
new 2960fb3 iOS: bump version to 0.9.3 (15)
new 4fcdeb2 iOS 15: show ToS
new 3714113 localizations, wording
new c0faa25 Atkinson Hyperlegible
new d9dde4b monospacedDigit
new 8a126ae PayTo URL listRowSeparator
new 01726ca SendDone
new 76b66a4 Sound for Expired
new 45985cc ToS
new 741d7e0 rendering on small screens
new 936e8d4 Warnings and hints no longer use "coins"
new d66b0de Expiration Constants
new 0ee1405 Move Status to top
new 95bf2e9 ToS, move Exchange down
new 4e71ef0 fanblades.slash and clock.badge.xmark not in iOS 15
new 1a5c9a9 extension TransactionsListView.Content => TransactionsRowsView
new 25ef2d8 Hints for manual withdrawal, Accessibility
new e12c1ac ToS
new 0b3bab0 Simplified
new 216b044 debug, cleanup
new 73dc3c1 Postpone update until onAppear
new 71bdc77 QRcode rendering and hint
new a2f8081 show up to 3 transactions in Balances
new 97ca40f small fixes
new 563902e Expired, pending
new 9ff0fd3 TransactionDetailView
new 8cdda29 Comments
new 297082c ScrollViewReader
new dbf44d6 iOS: bump version to 0.9.3 (16)
The 35 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:
.../Atkinson-Hyperlegible-Bold-102.otf | Bin 0 -> 36588 bytes
.../Atkinson-Hyperlegible-BoldItalic-102.otf | Bin 0 -> 37304 bytes
...tkinson-Hyperlegible-Font-License-2020-1104.pdf | Bin 0 -> 56016 bytes
.../Atkinson-Hyperlegible-Italic-102.otf | Bin 0 -> 35656 bytes
.../Atkinson-Hyperlegible-Regular-102.otf | Bin 0 -> 34436 bytes
Info.plist | 7 +
TalerWallet.xcodeproj/project.pbxproj | 40 +++--
TalerWallet1/Backend/Transaction.swift | 17 ++
TalerWallet1/Backend/WalletCore.swift | 15 +-
TalerWallet1/Controllers/Controller.swift | 3 +
TalerWallet1/Controllers/DebugViewC.swift | 2 +
TalerWallet1/Controllers/PublicConstants.swift | 4 +
TalerWallet1/Helper/AgePicker.swift | 2 +-
TalerWallet1/Helper/playSound.swift | 3 +-
TalerWallet1/Model/Model+Payment.swift | 24 ++-
TalerWallet1/Model/WalletModel.swift | 20 ++-
TalerWallet1/Views/Balances/BalanceRowView.swift | 1 +
TalerWallet1/Views/Balances/BalancesListView.swift | 29 +++-
.../Views/Balances/BalancesSectionView.swift | 31 +++-
TalerWallet1/Views/Balances/PendingRowView.swift | 1 +
TalerWallet1/Views/Exchange/ExchangeListView.swift | 1 -
TalerWallet1/Views/Exchange/ManualWithdraw.swift | 15 +-
.../Views/Exchange/ManualWithdrawDone.swift | 19 ++-
TalerWallet1/Views/Exchange/QuiteSomeCoins.swift | 39 ++---
TalerWallet1/Views/HelperViews/AmountView.swift | 1 +
.../Views/HelperViews/CurrencyInputView.swift | 2 +-
TalerWallet1/Views/HelperViews/LoadingView.swift | 3 +-
.../Views/HelperViews/QRCodeDetailView.swift | 34 ++--
TalerWallet1/Views/HelperViews/SelectDays.swift | 34 ++--
.../Views/HelperViews/TransactionButton.swift | 15 +-
TalerWallet1/Views/Main/MainView.swift | 1 +
TalerWallet1/Views/Main/WalletEmptyView.swift | 2 +-
TalerWallet1/Views/Payment/PaymentURIView.swift | 75 ++++++---
TalerWallet1/Views/Peer2peer/PaymentPurpose.swift | 4 +-
TalerWallet1/Views/Peer2peer/RequestPayment.swift | 8 +-
TalerWallet1/Views/Peer2peer/SendAmount.swift | 64 ++++---
.../Peer2peer/{SendNow.swift => SendDone.swift} | 68 ++++----
TalerWallet1/Views/Peer2peer/SendPurpose.swift | 4 +-
.../Settings/Pending/PendingOpsListView.swift | 19 +--
TalerWallet1/Views/Settings/SettingsView.swift | 69 +++++---
.../Views/Sheets/P2P_Sheets/P2pAcceptDone.swift | 50 +++---
.../Views/Sheets/P2P_Sheets/P2pPayURIView.swift | 2 +-
.../Sheets/P2P_Sheets/P2pReceiveURIView.swift | 9 +-
TalerWallet1/Views/Sheets/Sheet.swift | 4 +-
TalerWallet1/Views/Sheets/URLSheet.swift | 45 ++---
.../Views/Transactions/ManualDetails.swift | 28 ++--
TalerWallet1/Views/Transactions/ThreeAmounts.swift | 30 ++--
.../Views/Transactions/TransactionDetailView.swift | 62 ++++---
.../Views/Transactions/TransactionRowView.swift | 1 +
.../Views/Transactions/TransactionsListView.swift | 186 +++++++++------------
.../WithdrawAcceptDone.swift | 12 +-
.../WithdrawBankIntegrated/WithdrawTOSView.swift | 17 +-
.../WithdrawBankIntegrated/WithdrawURIView.swift | 7 +-
TestFlight/WhatToTest.en-US.txt | 22 +++
54 files changed, 685 insertions(+), 466 deletions(-)
create mode 100644 Atkinson-Hyperlegible/Atkinson-Hyperlegible-Bold-102.otf
create mode 100644
Atkinson-Hyperlegible/Atkinson-Hyperlegible-BoldItalic-102.otf
create mode 100644
Atkinson-Hyperlegible/Atkinson-Hyperlegible-Font-License-2020-1104.pdf
create mode 100644 Atkinson-Hyperlegible/Atkinson-Hyperlegible-Italic-102.otf
create mode 100644 Atkinson-Hyperlegible/Atkinson-Hyperlegible-Regular-102.otf
rename TalerWallet1/Views/Peer2peer/{SendNow.swift => SendDone.swift} (51%)
diff --git a/Atkinson-Hyperlegible/Atkinson-Hyperlegible-Bold-102.otf
b/Atkinson-Hyperlegible/Atkinson-Hyperlegible-Bold-102.otf
new file mode 100644
index 0000000..2e4985c
Binary files /dev/null and
b/Atkinson-Hyperlegible/Atkinson-Hyperlegible-Bold-102.otf differ
diff --git a/Atkinson-Hyperlegible/Atkinson-Hyperlegible-BoldItalic-102.otf
b/Atkinson-Hyperlegible/Atkinson-Hyperlegible-BoldItalic-102.otf
new file mode 100644
index 0000000..3e09177
Binary files /dev/null and
b/Atkinson-Hyperlegible/Atkinson-Hyperlegible-BoldItalic-102.otf differ
diff --git
a/Atkinson-Hyperlegible/Atkinson-Hyperlegible-Font-License-2020-1104.pdf
b/Atkinson-Hyperlegible/Atkinson-Hyperlegible-Font-License-2020-1104.pdf
new file mode 100644
index 0000000..afe27dc
Binary files /dev/null and
b/Atkinson-Hyperlegible/Atkinson-Hyperlegible-Font-License-2020-1104.pdf differ
diff --git a/Atkinson-Hyperlegible/Atkinson-Hyperlegible-Italic-102.otf
b/Atkinson-Hyperlegible/Atkinson-Hyperlegible-Italic-102.otf
new file mode 100644
index 0000000..cf0ab11
Binary files /dev/null and
b/Atkinson-Hyperlegible/Atkinson-Hyperlegible-Italic-102.otf differ
diff --git a/Atkinson-Hyperlegible/Atkinson-Hyperlegible-Regular-102.otf
b/Atkinson-Hyperlegible/Atkinson-Hyperlegible-Regular-102.otf
new file mode 100644
index 0000000..ea6cfb5
Binary files /dev/null and
b/Atkinson-Hyperlegible/Atkinson-Hyperlegible-Regular-102.otf differ
diff --git a/Info.plist b/Info.plist
index 8634a0f..6cbe85d 100644
--- a/Info.plist
+++ b/Info.plist
@@ -24,6 +24,13 @@
</array>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
+ <key>UIAppFonts</key>
+ <array>
+ <string>Atkinson-Hyperlegible-Regular-102.otf</string>
+ <string>Atkinson-Hyperlegible-Italic-102.otf</string>
+ <string>Atkinson-Hyperlegible-Bold-102.otf</string>
+ <string>Atkinson-Hyperlegible-BoldItalic-102.otf</string>
+ </array>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
diff --git a/TalerWallet.xcodeproj/project.pbxproj
b/TalerWallet.xcodeproj/project.pbxproj
index df18aaa..8352c2c 100644
--- a/TalerWallet.xcodeproj/project.pbxproj
+++ b/TalerWallet.xcodeproj/project.pbxproj
@@ -29,9 +29,12 @@
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
*/; };
- 4E7CFD382A532CE100CBAFF3 /* WhatToTest.en-US.txt in Resources
*/ = {isa = PBXBuildFile; fileRef = 4E7CFD372A532CE100CBAFF3 /*
WhatToTest.en-US.txt */; };
4E87C8732A31CB7F001C6406 /* TransactionsEmptyView.swift in
Sources */ = {isa = PBXBuildFile; fileRef = 4E87C8722A31CB7F001C6406 /*
TransactionsEmptyView.swift */; };
4E87C8752A34B411001C6406 /* UncompletedRowView.swift in Sources
*/ = {isa = PBXBuildFile; fileRef = 4E87C8742A34B411001C6406 /*
UncompletedRowView.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 */; };
+ 4E8C17232A6509BB005B2392 /*
Atkinson-Hyperlegible-BoldItalic-102.otf in Resources */ = {isa = PBXBuildFile;
fileRef = 4E8C171F2A6509BB005B2392 /* Atkinson-Hyperlegible-BoldItalic-102.otf
*/; };
4E8E25332A1CD39700A27BFA /* EqualIconWidthDomain.swift in
Sources */ = {isa = PBXBuildFile; fileRef = 4E8E25322A1CD39700A27BFA /*
EqualIconWidthDomain.swift */; };
4E9320432A14F6EA00A87B0E /* WalletColors.swift in Sources */ =
{isa = PBXBuildFile; fileRef = 4E9320422A14F6EA00A87B0E /* WalletColors.swift
*/; };
4E9320452A1645B600A87B0E /* RequestPayment.swift in Sources */
= {isa = PBXBuildFile; fileRef = 4E9320442A1645B600A87B0E /*
RequestPayment.swift */; };
@@ -48,7 +51,6 @@
4EB094DE29896D030043A8A1 /* TalerWalletUITests.swift in Sources
*/ = {isa = PBXBuildFile; fileRef = 4EB094DB29896D030043A8A1 /*
TalerWalletUITests.swift */; };
4EB094ED298979620043A8A1 /* TalerWallet1App.swift in Sources */
= {isa = PBXBuildFile; fileRef = 4EB094EC298979620043A8A1 /*
TalerWallet1App.swift */; };
4EB094F0298979D30043A8A1 /* Assets.xcassets in Resources */ =
{isa = PBXBuildFile; fileRef = 4EB094EF298979D30043A8A1 /* Assets.xcassets */;
};
- 4EB094F429897A510043A8A1 /* Preview Assets.xcassets in
Resources */ = {isa = PBXBuildFile; fileRef = 4EB094F329897A510043A8A1 /*
Preview Assets.xcassets */; };
4EB094F829897CA20043A8A1 /* FTalerWalletcore.framework in
Frameworks */ = {isa = PBXBuildFile; fileRef = 4EB094F729897CA20043A8A1 /*
FTalerWalletcore.framework */; };
4EB094FD29897D280043A8A1 /* SymLog in Frameworks */ = {isa =
PBXBuildFile; productRef = 4EB094FC29897D280043A8A1 /* SymLog */; };
4EB095032989C9BC0043A8A1 /* Controller.swift in Sources */ =
{isa = PBXBuildFile; fileRef = 4EB095012989C9BC0043A8A1 /* Controller.swift */;
};
@@ -92,7 +94,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 /* SendNow.swift in Sources */ = {isa
= PBXBuildFile; fileRef = 4EB3136029FEE79B007D68BC /* SendNow.swift */; };
+ 4EB3136129FEE79B007D68BC /* SendDone.swift in Sources */ = {isa
= PBXBuildFile; fileRef = 4EB3136029FEE79B007D68BC /* SendDone.swift */; };
4EB431672A1E55C700C5690E /* ManualWithdrawDone.swift in Sources
*/ = {isa = PBXBuildFile; fileRef = 4EB431662A1E55C700C5690E /*
ManualWithdrawDone.swift */; };
4EBA82AB2A3EB2CA00E5F39A /* TransactionButton.swift in Sources
*/ = {isa = PBXBuildFile; fileRef = 4EBA82AA2A3EB2CA00E5F39A /*
TransactionButton.swift */; };
4EBA82AD2A3F580500E5F39A /* QuiteSomeCoins.swift in Sources */
= {isa = PBXBuildFile; fileRef = 4EBA82AC2A3F580500E5F39A /*
QuiteSomeCoins.swift */; };
@@ -166,6 +168,10 @@
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>"; };
+ 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>"; };
+ 4E8C171F2A6509BB005B2392 /*
Atkinson-Hyperlegible-BoldItalic-102.otf */ = {isa = PBXFileReference;
lastKnownFileType = file; path = "Atkinson-Hyperlegible-BoldItalic-102.otf";
sourceTree = "<group>"; };
4E8E25322A1CD39700A27BFA /* EqualIconWidthDomain.swift */ =
{isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path =
EqualIconWidthDomain.swift; sourceTree = "<group>"; };
4E9320422A14F6EA00A87B0E /* WalletColors.swift */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path
= WalletColors.swift; sourceTree = "<group>"; };
4E9320442A1645B600A87B0E /* RequestPayment.swift */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path
= RequestPayment.swift; sourceTree = "<group>"; };
@@ -226,7 +232,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 /* SendNow.swift */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path
= SendNow.swift; sourceTree = "<group>"; };
+ 4EB3136029FEE79B007D68BC /* SendDone.swift */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path
= SendDone.swift; sourceTree = "<group>"; };
4EB431662A1E55C700C5690E /* ManualWithdrawDone.swift */ = {isa
= PBXFileReference; lastKnownFileType = sourcecode.swift; path =
ManualWithdrawDone.swift; sourceTree = "<group>"; };
4EBA82AA2A3EB2CA00E5F39A /* TransactionButton.swift */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path
= TransactionButton.swift; sourceTree = "<group>"; };
4EBA82AC2A3F580500E5F39A /* QuiteSomeCoins.swift */ = {isa =
PBXFileReference; lastKnownFileType = sourcecode.swift; path =
QuiteSomeCoins.swift; sourceTree = "<group>"; };
@@ -292,6 +298,17 @@
path = TestFlight;
sourceTree = "<group>";
};
+ 4E8C171B2A6509BB005B2392 /* Atkinson-Hyperlegible */ = {
+ isa = PBXGroup;
+ children = (
+ 4E8C171C2A6509BB005B2392 /*
Atkinson-Hyperlegible-Regular-102.otf */,
+ 4E8C171D2A6509BB005B2392 /*
Atkinson-Hyperlegible-Italic-102.otf */,
+ 4E8C171E2A6509BB005B2392 /*
Atkinson-Hyperlegible-Bold-102.otf */,
+ 4E8C171F2A6509BB005B2392 /*
Atkinson-Hyperlegible-BoldItalic-102.otf */,
+ );
+ path = "Atkinson-Hyperlegible";
+ sourceTree = SOURCE_ROOT;
+ };
4EB094EE298979840043A8A1 /* TalerWallet1 */ = {
isa = PBXGroup;
children = (
@@ -302,6 +319,7 @@
4EB095052989CB7C0043A8A1 /* Helper */,
4EB0950C2989CB9A0043A8A1 /* Quickjs */,
4EB094EF298979D30043A8A1 /* Assets.xcassets */,
+ 4E8C171B2A6509BB005B2392 /*
Atkinson-Hyperlegible */,
4E363CBF2A24754200D7E98C /* Settings.bundle */,
4EB094F529897A9A0043A8A1 /* Preview Content */,
);
@@ -520,7 +538,7 @@
children = (
4E40E0BD29F25ABB00B85369 /* SendAmount.swift */,
4E7940DD29FC307C00A9AEA1 /* SendPurpose.swift
*/,
- 4EB3136029FEE79B007D68BC /* SendNow.swift */,
+ 4EB3136029FEE79B007D68BC /* SendDone.swift */,
4E9320442A1645B600A87B0E /*
RequestPayment.swift */,
4E9320462A164BC700A87B0E /*
PaymentPurpose.swift */,
);
@@ -702,10 +720,12 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 4EB094F429897A510043A8A1 /* Preview
Assets.xcassets in Resources */,
4E363CC02A24754200D7E98C /* Settings.bundle in
Resources */,
+ 4E8C17202A6509BB005B2392 /*
Atkinson-Hyperlegible-Regular-102.otf in Resources */,
+ 4E8C17222A6509BB005B2392 /*
Atkinson-Hyperlegible-Bold-102.otf in Resources */,
+ 4E8C17232A6509BB005B2392 /*
Atkinson-Hyperlegible-BoldItalic-102.otf in Resources */,
+ 4E8C17212A6509BB005B2392 /*
Atkinson-Hyperlegible-Italic-102.otf in Resources */,
4EB094F0298979D30043A8A1 /* Assets.xcassets in
Resources */,
- 4E7CFD382A532CE100CBAFF3 /*
WhatToTest.en-US.txt in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -768,7 +788,7 @@
4EAD117629F672FA008EDD0B /*
KeyboardResponder.swift in Sources */,
4EB095572989CBFE0043A8A1 /*
TransactionRowView.swift in Sources */,
4EA1ABBE29A3833A008821EA /*
PublicConstants.swift in Sources */,
- 4EB3136129FEE79B007D68BC /* SendNow.swift in
Sources */,
+ 4EB3136129FEE79B007D68BC /* SendDone.swift in
Sources */,
4EB0956B2989CBFE0043A8A1 /*
TextFieldAlert.swift in Sources */,
4EBA82AD2A3F580500E5F39A /*
QuiteSomeCoins.swift in Sources */,
4EB431672A1E55C700C5690E /*
ManualWithdrawDone.swift in Sources */,
@@ -977,7 +997,7 @@
CODE_SIGN_ENTITLEMENTS = "GNU
Taler.entitlements";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone
Developer";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 14;
+ CURRENT_PROJECT_VERSION = 16;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = GUDDQ9428Y;
ENABLE_PREVIEWS = YES;
@@ -1019,7 +1039,7 @@
CODE_SIGN_ENTITLEMENTS = "GNU
Taler.entitlements";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone
Distribution";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 14;
+ CURRENT_PROJECT_VERSION = 16;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = GUDDQ9428Y;
ENABLE_PREVIEWS = YES;
diff --git a/TalerWallet1/Backend/Transaction.swift
b/TalerWallet1/Backend/Transaction.swift
index 08caed2..128a47a 100644
--- a/TalerWallet1/Backend/Transaction.swift
+++ b/TalerWallet1/Backend/Transaction.swift
@@ -69,6 +69,23 @@ enum TransactionMajorState: String, Codable {
case deleted
// Placeholder until D37 is fully implemented
case unknown
+
+ 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 .suspended: return "Suspended"
+ case .dialog: return String(localized: "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")
+ }
+ }
}
struct TransactionState: Codable, Hashable {
diff --git a/TalerWallet1/Backend/WalletCore.swift
b/TalerWallet1/Backend/WalletCore.swift
index 0d86cba..3def60d 100644
--- a/TalerWallet1/Backend/WalletCore.swift
+++ b/TalerWallet1/Backend/WalletCore.swift
@@ -186,16 +186,19 @@ extension WalletCore {
do {
let decoded = try JSONDecoder().decode(TransactionTransition.self,
from: jsonData)
if decoded.newTxState != decoded.oldTxState {
- if decoded.newTxState.major == .done {
- let components =
decoded.transactionId.components(separatedBy: [":"])
- if components.count >= 3 { // txn:$txtype:$uid
- if let type = TransactionType(rawValue: components[1])
{
+ let components = decoded.transactionId.components(separatedBy:
[":"])
+ if components.count >= 3 { // txn:$txtype:$uid
+ if let type = TransactionType(rawValue: components[1]) {
+ guard type != .refresh else { return }
+ if decoded.newTxState.major == .done {
Controller.shared.playSound(type.isIncoming ? 2 :
1)
+ } else if decoded.newTxState.major == .expired {
+ Controller.shared.playSound(0)
}
+ postNotification(.TransactionStateTransition,
+ userInfo: [TRANSACTIONTRANSITION:
decoded])
}
}
- postNotification(.TransactionStateTransition,
- userInfo: [TRANSACTIONTRANSITION: decoded])
}
} catch { // rethrows
symLog.log(jsonData) // TODO: .error
diff --git a/TalerWallet1/Controllers/Controller.swift
b/TalerWallet1/Controllers/Controller.swift
index 7f08bd2..96e1fef 100644
--- a/TalerWallet1/Controllers/Controller.swift
+++ b/TalerWallet1/Controllers/Controller.swift
@@ -5,6 +5,7 @@
import Foundation
import SwiftUI
import SymLog
+import os.log
enum BackendState {
case none
@@ -29,6 +30,7 @@ class Controller: ObservableObject {
@Published var backendState: BackendState = .none // only used for
launch animation
@AppStorage("playSounds") var playSounds: Bool = false // extension
mustn't define this, so it must be here
+ let logger = Logger (subsystem: "net.taler.gnu", category: "Controller")
var messageForSheet: String? = nil
@@ -59,6 +61,7 @@ class Controller: ObservableObject {
// MARK: -
extension Controller {
func openURL(_ url:URL) -> UrlCommand {
+ symLog.log(url)
guard let scheme = url.scheme else {return UrlCommand.unknown}
var uncrypted = false
switch scheme {
diff --git a/TalerWallet1/Controllers/DebugViewC.swift
b/TalerWallet1/Controllers/DebugViewC.swift
index 0d587db..f25b353 100644
--- a/TalerWallet1/Controllers/DebugViewC.swift
+++ b/TalerWallet1/Controllers/DebugViewC.swift
@@ -81,6 +81,7 @@ public let SHEET_RCV_REWARD = SHEET_PAYMENT + 10
// 150 Recei
// 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
// MARK: P2P Receive Coins
// p2p push credit - openURL (Link or scan QR)
@@ -118,6 +119,7 @@ struct DebugViewV: View {
Text(viewIDString)
.font(.caption2)
.foregroundColor(.red)
+ .monospacedDigit()
Spacer()
}
.edgesIgnoringSafeArea(.top)
diff --git a/TalerWallet1/Controllers/PublicConstants.swift
b/TalerWallet1/Controllers/PublicConstants.swift
index d98dd22..1be1113 100644
--- a/TalerWallet1/Controllers/PublicConstants.swift
+++ b/TalerWallet1/Controllers/PublicConstants.swift
@@ -7,6 +7,10 @@ import Foundation
public let LAUNCHDURATION: Double = 1.60
public let SLIDEDURATION: Double = 0.45
+public let ONEDAY: UInt = 1 // 1..3
+public let SEVENDAYS: UInt = 7 // 3..9
+public let THIRTYDAYS: UInt = 30 // 10..30
+
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/Helper/AgePicker.swift
b/TalerWallet1/Helper/AgePicker.swift
index 6f02d82..2622f39 100644
--- a/TalerWallet1/Helper/AgePicker.swift
+++ b/TalerWallet1/Helper/AgePicker.swift
@@ -30,7 +30,7 @@ struct AgePicker: View {
if ageMenuList.count > 1 {
VStack {
HStack {
- Text("If this wallet belongs to a child or teenager, the
generated coins should be age-restricted:")
+ Text("If this wallet belongs to a child or teenager, the
generated electronic cash should be age-restricted:")
.multilineTextAlignment(.leading)
.font(.footnote)
Spacer()
diff --git a/TalerWallet1/Helper/playSound.swift
b/TalerWallet1/Helper/playSound.swift
index ed39bef..0b4c428 100644
--- a/TalerWallet1/Helper/playSound.swift
+++ b/TalerWallet1/Helper/playSound.swift
@@ -11,10 +11,11 @@ extension Controller {
var soundID: SystemSoundID = 0
if number < 999 {
let sound = (number == 0) ? "payment_failure" :
- (number == 1) ? "payment_success" : "PaymentReceived"
+ (number == 1) ? "payment_success" : "PaymentReceived"
let fileURL = URL(fileURLWithPath:
"/System/Library/Audio/UISounds/"
+ sound + ".caf")
AudioServicesCreateSystemSoundID(fileURL as CFURL, &soundID)
+ logger.log("\(sound, privacy: .public) \(soundID)")
} else {
soundID = UInt32(number)
}
diff --git a/TalerWallet1/Model/Model+Payment.swift
b/TalerWallet1/Model/Model+Payment.swift
index 6c60846..51e8d57 100644
--- a/TalerWallet1/Model/Model+Payment.swift
+++ b/TalerWallet1/Model/Model+Payment.swift
@@ -114,19 +114,31 @@ enum PreparePayResultType: String, Codable {
case insufficientBalance = "insufficient-balance"
}
+struct PayMerchantInsufficientBalanceDetails: Codable {
+ let amountRequested: Amount
+ let balanceAvailable: Amount
+ let balanceMaterial: Amount
+ let balanceAgeAcceptable: Amount
+ let balanceMerchantAcceptable: Amount
+ let balanceMerchantDepositable: Amount
+ let feeGapEstimate: Amount
+}
+
/// The result from PreparePayForUri
-struct PaymentDetailsForUri: Codable {
+struct PreparePayResult: Codable {
let status: PreparePayResultType
let transactionId: String
let contractTerms: MerchantContractTerms
- let contractTermsHash: String
+ let contractTermsHash: String? // only if
status != insufficientBalance
let amountRaw: Amount
- let amountEffective: Amount
- let talerUri: String
+ let amountEffective: Amount? // only if
status != insufficientBalance
+ let balanceDetails: PayMerchantInsufficientBalanceDetails? // only if
status == insufficientBalance
+ let paid: Bool? // only if
status == alreadyConfirmed
+// let talerUri: String?
}
/// A request to get an exchange's payment contract terms.
fileprivate struct PreparePayForUri: WalletBackendFormattedRequest {
- typealias Response = PaymentDetailsForUri
+ typealias Response = PreparePayResult
func operation() -> String { return "preparePayForUri" }
func args() -> Args { return Args(talerPayUri: talerPayUri) }
@@ -158,7 +170,7 @@ extension WalletModel {
/// load payment details. Networking involved
@MainActor
func preparePayForUriM(_ talerPayUri: String) // M for MainActor
- async throws -> PaymentDetailsForUri {
+ async throws -> PreparePayResult {
let request = PreparePayForUri(talerPayUri: talerPayUri)
let response = try await sendRequest(request, ASYNCDELAY)
return response
diff --git a/TalerWallet1/Model/WalletModel.swift
b/TalerWallet1/Model/WalletModel.swift
index 1b56aa2..1de0aff 100644
--- a/TalerWallet1/Model/WalletModel.swift
+++ b/TalerWallet1/Model/WalletModel.swift
@@ -98,7 +98,7 @@ fileprivate struct InitRequest: WalletBackendFormattedRequest
{
var versionInfo: VersionInfo
}
}
-// MARK: -
+
extension WalletModel {
/// initalize Wallet-Core. Will do networking
func initWalletCoreT() async throws -> VersionInfo {
@@ -124,3 +124,21 @@ extension WalletModel {
}
}
}
+// MARK: -
+/// A request to initialize Wallet-core
+fileprivate struct ResetRequest: WalletBackendFormattedRequest {
+ func operation() -> String { return "reset" }
+ func args() -> Args { return Args() }
+
+ struct Args: Encodable {} // no arguments needed
+ struct Response: Decodable {}
+}
+
+extension WalletModel {
+ /// reset Wallet-Core
+ func resetWalletCoreT() async throws {
+ // T for any Thread
+ let request = ResetRequest()
+ _ = try await sendRequest(request, 0)
+ }
+}
diff --git a/TalerWallet1/Views/Balances/BalanceRowView.swift
b/TalerWallet1/Views/Balances/BalanceRowView.swift
index 5c215b3..89a5a15 100644
--- a/TalerWallet1/Views/Balances/BalanceRowView.swift
+++ b/TalerWallet1/Views/Balances/BalanceRowView.swift
@@ -23,6 +23,7 @@ struct BalanceButton: View {
}
Text(verbatim: "\(amount.valueStr)") // TODO:
CurrencyFormatter?
.font(.title)
+ .monospacedDigit()
}
} .disabled(false)
.accessibilityElement(children:
/*@START_MENU_TOKEN@*/.ignore/*@END_MENU_TOKEN@*/)
diff --git a/TalerWallet1/Views/Balances/BalancesListView.swift
b/TalerWallet1/Views/Balances/BalancesListView.swift
index 790c4ee..934acb2 100644
--- a/TalerWallet1/Views/Balances/BalancesListView.swift
+++ b/TalerWallet1/Views/Balances/BalancesListView.swift
@@ -8,9 +8,8 @@ import SymLog
import AVFoundation
/// This view shows the list of balances / currencies, each in its own section
-
struct BalancesListView: View {
- private let symLog = SymLogV(0)
+ private let symLog = SymLogV()
let navTitle: String
let hamburgerAction: () -> Void
@@ -86,7 +85,6 @@ struct BalancesListView: View {
centsToTransfer: $centsToTransfer, summary: $summary,
reloadAction: reloadAction)
.navigationTitle(navTitle)
- .navigationBarTitleDisplayMode(.automatic)
.navigationBarItems(leading: HamburgerButton(action:
hamburgerAction),
trailing: QRButton(action:
checkCameraAvailable))
.overlay {
@@ -131,14 +129,19 @@ extension BalancesListView {
@Binding var summary: String
var reloadAction: () async -> Int
+ @State private var isActive = true
+ @State private var shouldReload = false
+
var body: some View {
#if DEBUG
let _ = Self._printChanges()
let _ = symLog?.vlog() // just to get the # to compare it
with .onAppear & onDisappear
#endif
Group { // necessary for .backslide transition (bug in SwiftUI)
+ let count = balances.count
List(balances, id: \.self) { balance in
BalancesSectionView(balance: balance,
+ sectionCount: count,
centsToTransfer: $centsToTransfer,
summary: $summary)
}
@@ -152,12 +155,26 @@ extension BalancesListView {
}
.listStyle(myListStyle.style).anyView
}
+ .onAppear() {
+ isActive = true
+ if shouldReload {
+ shouldReload = false
+ symLog?.log(".onAppear ==> shouldReload was true,
reloading now")
+ Task { await reloadAction() }
+ }
+ }
+ .onDisappear() {
+ isActive = false
+ }
.onNotification(.BalanceChange) { notification in
// reload balances on receiving BalanceChange notification ...
// doesn't need to be received on main thread because we just
reload in a background task anyway
- symLog?.log(".onNotification(.BalanceChange) ==> reload")
- Task {
- await reloadAction()
+ if isActive {
+ symLog?.log(".onNotification(.BalanceChange) ==> reload")
+ Task { await reloadAction() }
+ } else {
+ symLog?.log(".onNotification(.BalanceChange) ==> reload
postponed, shouldReload = true")
+ shouldReload = true
}
}
} // body
diff --git a/TalerWallet1/Views/Balances/BalancesSectionView.swift
b/TalerWallet1/Views/Balances/BalancesSectionView.swift
index de1bfaa..6cf640c 100644
--- a/TalerWallet1/Views/Balances/BalancesSectionView.swift
+++ b/TalerWallet1/Views/Balances/BalancesSectionView.swift
@@ -16,7 +16,8 @@ import SymLog
struct BalancesSectionView: View {
private let symLog = SymLogV()
- var balance:Balance
+ let balance: Balance
+ let sectionCount: Int
@Binding var centsToTransfer: UInt64
@Binding var summary: String
@@ -82,7 +83,7 @@ struct BalancesSectionView: View {
Section {
if "KUDOS" == currency && !balance.available.isZero {
- Text("You can spend these KUDOS in the [Demo
Shop](https://shop.demo.taler.net), or send coins to another wallet.")
+ Text("You can spend these KUDOS in the [Demo
Shop](https://shop.demo.taler.net), or send them to another wallet.")
.multilineTextAlignment(.leading)
}
HStack(spacing: 0) {
@@ -174,11 +175,36 @@ struct BalancesSectionView: View {
transactions = response
pendingTransactions = WalletModel.pendingTransactions(response)
uncompletedTransactions =
WalletModel.uncompletedTransactions(response)
+ completedTransactions =
WalletModel.completedTransactions(response)
shownSectionID = sectionID
// } else {
// symLog.log("task for BalancesSectionView \(sectionID) ❗️
skip reloading Transactions")
// }
}
+ let transactionCount = completedTransactions.count
+ 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 threeTransactions = Array(slice)
+ TransactionsRowsView(symLog: symLog,
+ currency: currency,
+ transactions: threeTransactions,
+ reloadOneAction: reloadOneAction)
+ } header: {
+ Text("Last transactions")
+ .font(.callout)
+ }
+ }
} // body
}
// MARK: -
@@ -194,6 +220,7 @@ fileprivate struct BindingViewContainer : View {
requiresUserInput: false,
hasPendingTransactions: true)
BalancesSectionView(balance: balance,
+ sectionCount: 2,
centsToTransfer: $centsToTransfer,
summary: $summary)
}
diff --git a/TalerWallet1/Views/Balances/PendingRowView.swift
b/TalerWallet1/Views/Balances/PendingRowView.swift
index 5825fce..657b1a6 100644
--- a/TalerWallet1/Views/Balances/PendingRowView.swift
+++ b/TalerWallet1/Views/Balances/PendingRowView.swift
@@ -28,6 +28,7 @@ struct PendingRowView: View {
Text(valueStr)
.font(.title)
.foregroundColor(WalletColors().pendingColor(incoming))
+ .monospacedDigit()
// Text("PENDING")
// .font(.callout)
// .foregroundColor(WalletColors().pendingColor(incoming))
diff --git a/TalerWallet1/Views/Exchange/ExchangeListView.swift
b/TalerWallet1/Views/Exchange/ExchangeListView.swift
index 45ea4a1..f36d510 100644
--- a/TalerWallet1/Views/Exchange/ExchangeListView.swift
+++ b/TalerWallet1/Views/Exchange/ExchangeListView.swift
@@ -54,7 +54,6 @@ struct ExchangeListView: View {
centsToTransfer: $centsToTransfer,
reloadAction: reloadAction)
.navigationTitle(navTitle)
- .navigationBarTitleDisplayMode(.automatic)
.navigationBarItems(leading: HamburgerButton(action: hamburgerAction),
trailing: PlusButton(action: plusAction)
.accessibilityLabel("Add Exchange"))
diff --git a/TalerWallet1/Views/Exchange/ManualWithdraw.swift
b/TalerWallet1/Views/Exchange/ManualWithdraw.swift
index 9e350ab..6077474 100644
--- a/TalerWallet1/Views/Exchange/ManualWithdraw.swift
+++ b/TalerWallet1/Views/Exchange/ManualWithdraw.swift
@@ -30,16 +30,16 @@ struct ManualWithdraw: View {
let currencyField = CurrencyField(value: $centsToTransfer, currency:
currency) // becomeFirstResponder
// let agePicker = AgePicker(ageMenuList: $ageMenuList, selectedAge:
$selectedAge)
- ScrollViewReader { scrollView in
+ ScrollView {
VStack {
- Text("from \(exchange.exchangeBaseUrl.trimURL())")
- .font(.title3)
CurrencyInputView(currencyField: currencyField,
title: String(localized: "Amount to
withdraw:"))
-
let someCoins = SomeCoins(details: withdrawalAmountDetails)
QuiteSomeCoins(someCoins: someCoins, shouldShowFee: true,
currency: currency, amountEffective:
withdrawalAmountDetails?.amountEffective)
+ Text(exchange.exchangeBaseUrl.trimURL())
+ .multilineTextAlignment(.center)
+// .font(.title3)
let disabled = (centsToTransfer == 0) || someCoins.invalid ||
someCoins.tooMany
if !disabled {
@@ -58,12 +58,15 @@ struct ManualWithdraw: View {
Text("Confirm Withdrawal") //
VIEW_WITHDRAW_ACCEPT
}.buttonStyle(TalerButtonStyle(type: .prominent))
} else {
+ Text("You must accept the Terms of Service first
before you can withdraw electronic cash to your wallet.")
+ .multilineTextAlignment(.leading)
+ .padding()
NavigationLink(destination: LazyView {
WithdrawTOSView(exchangeBaseUrl:
exchange.exchangeBaseUrl,
viewID:
VIEW_WITHDRAW_TOS,
acceptAction: nil)
// pop back to here
}) {
- Text("Check Terms of Service") //
VIEW_WITHDRAW_TOS
+ Text("Read Terms of Service") //
VIEW_WITHDRAW_TOS
}.buttonStyle(TalerButtonStyle(type: .prominent))
}
}
@@ -79,7 +82,7 @@ struct ManualWithdraw: View {
symLog.log("onAppear")
DebugViewC.shared.setViewID(VIEW_WITHDRAWAL)
}
- .task(id: centsToTransfer) {
+ .task(id: centsToTransfer) { // re-run this whenever centsToTransfer
changes
let amount = Amount.amountFromCents(currency, centsToTransfer)
do {
withdrawalAmountDetails = try await
model.loadWithdrawalDetailsForAmountM(exchange.exchangeBaseUrl, amount: amount)
diff --git a/TalerWallet1/Views/Exchange/ManualWithdrawDone.swift
b/TalerWallet1/Views/Exchange/ManualWithdrawDone.swift
index 0048820..e5d3b20 100644
--- a/TalerWallet1/Views/Exchange/ManualWithdrawDone.swift
+++ b/TalerWallet1/Views/Exchange/ManualWithdrawDone.swift
@@ -16,8 +16,8 @@ struct ManualWithdrawDone: View {
@EnvironmentObject private var model: WalletModel
- @State var acceptManualWithdrawalResult: AcceptManualWithdrawalResult?
- @State var transactionId: String?
+ @State private var acceptManualWithdrawalResult:
AcceptManualWithdrawalResult?
+ @State private var transactionId: String?
func reloadOneAction(_ transactionId: String) async throws -> Transaction {
return try await model.getTransactionByIdT(transactionId)
@@ -28,13 +28,20 @@ struct ManualWithdrawDone: View {
let _ = Self._printChanges()
let _ = symLog.vlog() // just to get the # to compare it with
.onAppear & onDisappear
#endif
- VStack {
+ Group {
if let transactionId {
TransactionDetailView(transactionId: transactionId,
reloadAction: reloadOneAction,
- doneAction:
ViewState.shared.popToRootView)
- .navigationBarBackButtonHidden(true) // exit only
by Done-Button
- .navigationTitle(navTitle)
+ navTitle: navTitle,
+ doneAction:
ViewState.shared.popToRootView,
+ abortAction: nil,
+ deleteAction: nil,
+ failAction: nil,
+ suspendAction: nil,
+ resumeAction: nil)
+ .navigationBarBackButtonHidden(true)
+ .interactiveDismissDisabled() // can only use "Done"
button to dismiss
+// .navigationTitle(navTitle)
} else {
WithdrawProgressView(message:
exchange.exchangeBaseUrl.trimURL())
.navigationTitle("Loading " + navTitle)
diff --git a/TalerWallet1/Views/Exchange/QuiteSomeCoins.swift
b/TalerWallet1/Views/Exchange/QuiteSomeCoins.swift
index 02c1ce1..aa00586 100644
--- a/TalerWallet1/Views/Exchange/QuiteSomeCoins.swift
+++ b/TalerWallet1/Views/Exchange/QuiteSomeCoins.swift
@@ -54,42 +54,25 @@ struct QuiteSomeCoins: View {
let amountEffective: Amount?
var body: some View {
- if shouldShowFee {
- Text(someCoins.invalid ? "Invalid amount"
- : someCoins.tooMany ? "Too many coins for a single withdrawal"
- : someCoins.hasFee ? "- \(someCoins.fee) withdrawal fee"
- : "No withdrawal fee")
- .foregroundColor((someCoins.invalid || someCoins.tooMany ||
someCoins.hasFee) ? .red : .primary)
- .padding(4)
- }
if !someCoins.invalid {
- HStack {
- let coins: String = someCoins.unknown ? String(localized:
"Some", comment: "unknown number of coins")
- : "\(someCoins.numCoins)"
- Text(coins)
- .foregroundColor(someCoins.quiteSome ? .red : .primary)
- Text(someCoins.tooMany ? "coins" : "coins to obtain:")
- .foregroundColor(someCoins.tooMany ? .red : .primary)
-
- Spacer()
- if !someCoins.tooMany {
- let effective = amountEffective ?? Amount(currency:
currency, value: 0)
- Text(effective.readableDescription)
- }
- } // xx coins to obtain: YYY currency
-// .font(.title3)
- .padding(.top)
-
if !someCoins.tooMany {
if someCoins.manyCoins {
- Text(someCoins.quiteSome ? "Warning: It will take quite
some time\nto generate this many coins!"
- : "Warning: It will take some
time\nto generate this many coins.")
+ Text(someCoins.quiteSome ? "Warning: It will take quite
some time to encrypt this amount!"
+ : "Warning: It will take some
time to encrypt this amount.")
.multilineTextAlignment(.leading)
- .padding(.top, 6)
+ .padding(.vertical, 6)
.foregroundColor(someCoins.quiteSome ? .red : .primary)
} // warnings
}
}
+ if shouldShowFee {
+ Text(someCoins.invalid ? "Amount too small!"
+ : someCoins.tooMany ? "Amount too big for a single withdrawal!"
+ : someCoins.hasFee ? "- \(someCoins.fee) fee"
+ : "No withdrawal fee")
+ .foregroundColor((someCoins.invalid || someCoins.tooMany ||
someCoins.hasFee) ? .red : .primary)
+// .padding(4)
+ }
}
}
// MARK: -
diff --git a/TalerWallet1/Views/HelperViews/AmountView.swift
b/TalerWallet1/Views/HelperViews/AmountView.swift
index 1d059cb..ceaa457 100644
--- a/TalerWallet1/Views/HelperViews/AmountView.swift
+++ b/TalerWallet1/Views/HelperViews/AmountView.swift
@@ -22,6 +22,7 @@ struct AmountView: View {
.font(large ? .title : .title2)
// .fontWeight(large ? .medium : .regular) //
@available(iOS 16.0, *)
.foregroundColor(color)
+ .monospacedDigit()
Spacer()
}
}
diff --git a/TalerWallet1/Views/HelperViews/CurrencyInputView.swift
b/TalerWallet1/Views/HelperViews/CurrencyInputView.swift
index da84250..e6f0d38 100644
--- a/TalerWallet1/Views/HelperViews/CurrencyInputView.swift
+++ b/TalerWallet1/Views/HelperViews/CurrencyInputView.swift
@@ -16,7 +16,7 @@ struct CurrencyInputView: View {
var body: some View {
VStack (alignment: .leading) {
Text(title)
- .padding(.top)
+// .padding(.top)
.font(.title3)
currencyField
.frame(maxWidth: .infinity, alignment: .trailing)
diff --git a/TalerWallet1/Views/HelperViews/LoadingView.swift
b/TalerWallet1/Views/HelperViews/LoadingView.swift
index 0c1c452..10450fc 100644
--- a/TalerWallet1/Views/HelperViews/LoadingView.swift
+++ b/TalerWallet1/Views/HelperViews/LoadingView.swift
@@ -23,6 +23,7 @@ struct LoadingView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
LoadingView(backButtonHidden: true)
- }
+ .navigationBarTitleDisplayMode(.automatic)
+ }.navigationViewStyle(.stack)
}
}
diff --git a/TalerWallet1/Views/HelperViews/QRCodeDetailView.swift
b/TalerWallet1/Views/HelperViews/QRCodeDetailView.swift
index e155c48..dfacf5e 100644
--- a/TalerWallet1/Views/HelperViews/QRCodeDetailView.swift
+++ b/TalerWallet1/Views/HelperViews/QRCodeDetailView.swift
@@ -10,25 +10,37 @@ import AVFoundation
struct QRCodeDetailView: View {
let talerURI: String
let incoming: Bool
+ let amount: Amount?
var body: some View {
if talerURI.count > 10 {
- VStack {
- Text(incoming ? "Let the payer scan this QR code to pay:"
- : "Let the payee scan this QR code to receive:")
- .fixedSize(horizontal: false, vertical: true)
- .padding(.top, 30)
+ VStack (alignment: .leading) {
+ // TODO: use currency formatter instead of .readableDescription
+ let amountStr = (amount == nil) ?
+ (incoming ? String(localized: "Let the payer scan this QR
code to pay:")
+ : String(localized: "Let the payee scan this QR
code to receive:"))
+ : (incoming ? String(localized: "Let the payer scan this QR
code to pay \(amount!.readableDescription):",
+ comment: "amount.readableDescription:
5,3 €")
+ : String(localized: "Let the payee scan this QR
code to receive \(amount!.readableDescription):",
+ comment: "amount.readableDescription:
7.41 $"))
+ Text(amountStr)
+ .fixedSize(horizontal: false, vertical: true) //
wrap in scrollview
+// .padding(.top, 30)
.font(.title3)
+ HStack {
+ Spacer()
+ QRGeneratorView(text: talerURI)
+ Spacer()
+ }
- QRGeneratorView(text: talerURI)
-// Text(talerURI)
-
- Text("Alternatively, copy and send this URI:")
- .fixedSize(horizontal: false, vertical: true)
+ Text("Alternatively, copy and send this link:")
+ .multilineTextAlignment(.leading)
.font(.title3)
.padding(.vertical)
Text(talerURI)
+ .multilineTextAlignment(.center)
+ .fixedSize(horizontal: false, vertical: true) //
wrap in scrollview
.padding(.bottom)
CopyShare(textToCopy: talerURI)
@@ -44,7 +56,7 @@ fileprivate struct ContentView: View {
var body: some View {
List {
- QRCodeDetailView(talerURI: talerURI, incoming: false)
+ QRCodeDetailView(talerURI: talerURI, incoming: false, amount: nil)
}
}
}
diff --git a/TalerWallet1/Views/HelperViews/SelectDays.swift
b/TalerWallet1/Views/HelperViews/SelectDays.swift
index 9c982e5..208c4e2 100644
--- a/TalerWallet1/Views/HelperViews/SelectDays.swift
+++ b/TalerWallet1/Views/HelperViews/SelectDays.swift
@@ -19,36 +19,48 @@ struct SelectDays: View {
let maxExpiration: UInt
func oneDayAction() -> Void {
- selected = 1
+ selected = ONEDAY
symLog.log(selected)
}
func sevenDayAction() -> Void {
- selected = 7
+ selected = SEVENDAYS
symLog.log(selected)
}
func thirtyDayAction() -> Void {
- selected = 30
+ selected = THIRTYDAYS
symLog.log(selected)
}
var body: some View {
HStack {
Button(action: oneDayAction) {
- Text(developerMode ? "3 Min." : "1 Day")
- }.buttonStyle(TalerButtonStyle(type: (selected == 1) ? .prominent
: .bordered, dimmed: true))
+ 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)
Button(action: sevenDayAction) {
- Text(developerMode ? "1 Hour" : "7 Days")
- }.buttonStyle(TalerButtonStyle(type: (selected == 7) ? .prominent
: .bordered, dimmed: true))
- .disabled(!isEnabled || maxExpiration < 7)
+ 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)
Button(action: thirtyDayAction) {
- Text(developerMode ? "1 Day" : "30 Days")
- }.buttonStyle(TalerButtonStyle(type: (selected == 30) ? .prominent
: .bordered, dimmed: true))
- .disabled(!isEnabled || maxExpiration < 30)
+ 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
}
}
diff --git a/TalerWallet1/Views/HelperViews/TransactionButton.swift
b/TalerWallet1/Views/HelperViews/TransactionButton.swift
index ed4f3fa..4c17030 100644
--- a/TalerWallet1/Views/HelperViews/TransactionButton.swift
+++ b/TalerWallet1/Views/HelperViews/TransactionButton.swift
@@ -49,19 +49,23 @@ struct TransactionButton: View {
switch command {
case .delete:
Text("Delete from list" + spaces)
- Image(systemName: "trash") //
+ Image(systemName: "trash")
//
case .abort:
Text("Abort" + spaces)
- Image(systemName: "x.circle") //
+ Image(systemName: "x.circle")
//
case .fail:
Text("Fail" + spaces)
- Image(systemName: "fanblades.slash") //
+ Image(systemName: "play.slash")
//
case .suspend:
Text("Suspend" + spaces)
- Image(systemName: "clock.badge.xmark") //
+ if #available(iOS 16.0, *) {
+ Image(systemName: "clock.badge.xmark")
//
+ } else {
+ Image(systemName:
"clock.badge.exclamationmark")//
+ }
case .resume:
Text("Resume" + spaces)
- Image(systemName: "clock.arrow.circlepath") //
+ Image(systemName: "clock.arrow.circlepath")
//
}
}
}
@@ -70,7 +74,6 @@ struct TransactionButton: View {
})
.buttonStyle(.bordered)
.controlSize(.large)
- .padding(.horizontal)
.disabled(disabled)
}
diff --git a/TalerWallet1/Views/Main/MainView.swift
b/TalerWallet1/Views/Main/MainView.swift
index 810e052..e81d23e 100644
--- a/TalerWallet1/Views/Main/MainView.swift
+++ b/TalerWallet1/Views/Main/MainView.swift
@@ -113,6 +113,7 @@ extension MainView {
.frame(maxWidth: .infinity, maxHeight: .infinity,
alignment: .center)
.transition(.backslide)
}
+ .navigationBarTitleDisplayMode(.automatic)
}.navigationViewStyle(.stack)
// The side view is on top of the current view
SideBarView(views: views,
diff --git a/TalerWallet1/Views/Main/WalletEmptyView.swift
b/TalerWallet1/Views/Main/WalletEmptyView.swift
index d095ce2..300248b 100644
--- a/TalerWallet1/Views/Main/WalletEmptyView.swift
+++ b/TalerWallet1/Views/Main/WalletEmptyView.swift
@@ -24,7 +24,7 @@ struct WalletEmptyView: View {
Link(DEMOBANK, destination: URL(string: DEMOBANK)!)
}
Section {
- Text("Just register a test account, then withdraw some coins.")
+ Text("Just register a test account, then withdraw some
electronic cash.")
}
}
.listStyle(myListStyle.style).anyView
diff --git a/TalerWallet1/Views/Payment/PaymentURIView.swift
b/TalerWallet1/Views/Payment/PaymentURIView.swift
index a42ddc2..4b0150d 100644
--- a/TalerWallet1/Views/Payment/PaymentURIView.swift
+++ b/TalerWallet1/Views/Payment/PaymentURIView.swift
@@ -20,11 +20,11 @@ struct PaymentURIView: View {
@EnvironmentObject private var model: WalletModel
- func acceptAction(detailsForUri: PaymentDetailsForUri) {
+ func acceptAction(preparePayResult: PreparePayResult) {
Task {
do {
- let confirmPayResult = try await
model.confirmPayM(detailsForUri.transactionId)
- symLog.log(confirmPayResult as Any)
+ let confirmPayResult = try await
model.confirmPayM(preparePayResult.transactionId)
+// symLog.log(confirmPayResult as Any)
if confirmPayResult.type != "done" {
controller.playSound(0)
// TODO: show error
@@ -38,42 +38,61 @@ struct PaymentURIView: View {
}
}
- @State var detailsForUri: PaymentDetailsForUri? = nil
+ @State var preparePayResult: PreparePayResult? = nil
var body: some View {
- if let detailsForUri {
- ScrollViewReader { scrollView in
+ if let preparePayResult {
+ let effective = preparePayResult.amountEffective
List {
- let baseURL = detailsForUri.contractTerms.exchanges.first?.url
- let raw = detailsForUri.amountRaw
- let effective = detailsForUri.amountEffective
+ let baseURL =
preparePayResult.contractTerms.exchanges.first?.url
+ let raw = preparePayResult.amountRaw
let currency = raw.currencyStr
- let fee = try! Amount.diff(raw, effective) // TODO:
different currencies
- ThreeAmountsView(topTitle: String(localized: "Amount to pay:"),
- topAmount: raw, fee: fee,
- bottomTitle: String(localized: "\(currency) to
be spent:"),
- bottomAmount: effective,
- large: false, pending: false, incoming:
false,
- baseURL: baseURL)
- // TODO: payment: popup with all possible exchanges, check fees
+ let topTitle = String(localized: "Amount to pay:")
+ if let effective {
+ // TODO: already paid
+ let fee = try! Amount.diff(raw, effective) // TODO:
different currencies
+ ThreeAmountsView(topTitle: topTitle,
+ topAmount: raw, fee: fee,
+ bottomTitle: String(localized:
"\(currency) to be spent:"),
+ 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)")
+ ThreeAmountsView(topTitle: topTitle,
+ topAmount: raw, fee: nil,
+ bottomTitle: String(localized:
"\(currency) available:"),
+ bottomAmount:
balanceDetails.balanceAvailable,
+ large: false, pending: false, incoming:
false,
+ baseURL: baseURL)
+ } else {
+ // TODO: Error - neither effective nor balanceDetails
+ Text("Error")
+ }
}
.listStyle(myListStyle.style).anyView
.safeAreaInset(edge: .bottom) {
- Button(navTitle, action: { acceptAction(detailsForUri:
detailsForUri) })
- .buttonStyle(TalerButtonStyle(type: .prominent))
- .padding(.horizontal)
+ if let effective {
+ Button(navTitle, action: { acceptAction(preparePayResult:
preparePayResult) })
+ .buttonStyle(TalerButtonStyle(type: .prominent))
+ .padding(.horizontal)
+ } else {
+ Button("Cancel", action: { dismissTop() })
+ .buttonStyle(TalerButtonStyle(type: .bordered))
+ .padding(.horizontal)
+ }
}
.navigationTitle(navTitle)
- } // ScrollViewReader
} else {
- let badURL = "Error in URL: \(url)"
+ let badURL = "Error in Link: \(url)"
WithdrawProgressView(message: url.host ?? badURL)
.navigationTitle("Find Exchange")
.task {
do {
symLog.log(".task")
- let details = try await
model.preparePayForUriM(url.absoluteString)
- detailsForUri = details
+ let result = try await
model.preparePayForUriM(url.absoluteString)
+ preparePayResult = result
} catch { // TODO: error
symLog.log(error.localizedDescription)
}
@@ -116,17 +135,19 @@ struct PaymentURIView_Previews: PreviewProvider {
extra: extra
// auditors: [],
)
- let details = PaymentDetailsForUri(
+ let details = PreparePayResult(
status: PreparePayResultType.paymentPossible,
transactionId: "txn:payment:012345",
contractTerms: terms,
contractTermsHash: "termsHash",
amountRaw: try! Amount(fromString: LONGCURRENCY + ":2.2"),
amountEffective: try! Amount(fromString: LONGCURRENCY + ":2.4"),
- talerUri: "talerURI"
+ balanceDetails: nil,
+ paid: nil
+// , talerUri: "talerURI"
)
let url = URL(string: "taler://pay/some_amount")!
- PaymentURIView(url: url, detailsForUri: details)
+ PaymentURIView(url: url, preparePayResult: details)
}
}
diff --git a/TalerWallet1/Views/Peer2peer/PaymentPurpose.swift
b/TalerWallet1/Views/Peer2peer/PaymentPurpose.swift
index a608488..373aceb 100644
--- a/TalerWallet1/Views/Peer2peer/PaymentPurpose.swift
+++ b/TalerWallet1/Views/Peer2peer/PaymentPurpose.swift
@@ -58,14 +58,14 @@ struct PaymentPurpose: View {
Text("Expires in:")
.font(.title3)
- SelectDays(selected: $expireDays, maxExpiration: 35)
+ SelectDays(selected: $expireDays, maxExpiration: THIRTYDAYS)
.disabled(false)
.padding(.bottom)
let disabled = (expireDays == 0) || (summary.count < 1)
NavigationLink(destination: LazyView {
- SendNow(amountToSend: nil,
+ SendDone(amountToSend: nil,
amountToReceive: amount,
summary: summary, expireDays: expireDays)
}) {
diff --git a/TalerWallet1/Views/Peer2peer/RequestPayment.swift
b/TalerWallet1/Views/Peer2peer/RequestPayment.swift
index f0d5085..18ee298 100644
--- a/TalerWallet1/Views/Peer2peer/RequestPayment.swift
+++ b/TalerWallet1/Views/Peer2peer/RequestPayment.swift
@@ -6,7 +6,7 @@ import SwiftUI
import taler_swift
import SymLog
-// Will be called by the user tapping "Request Payment" in the balances list
+// Called when tapping "Request Payment" in the balances list
struct RequestPayment: View {
private let symLog = SymLogV()
@@ -28,8 +28,7 @@ struct RequestPayment: View {
let navTitle = String(localized: "Request \(currency)", comment:
"Request currency, Dialog Title")
let currencyField = CurrencyField(value: $centsToTransfer, currency:
currency)
- ScrollViewReader { scrollView in
- VStack {
+ ScrollView { VStack {
CurrencyInputView(currencyField: currencyField,
title: String(localized: "Amount to receive:"))
@@ -54,8 +53,7 @@ struct RequestPayment: View {
.disabled(disabled)
}
Spacer()
- }
- }
+ } }
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal)
.background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
diff --git a/TalerWallet1/Views/Peer2peer/SendAmount.swift
b/TalerWallet1/Views/Peer2peer/SendAmount.swift
index 3acc86f..c5d152d 100644
--- a/TalerWallet1/Views/Peer2peer/SendAmount.swift
+++ b/TalerWallet1/Views/Peer2peer/SendAmount.swift
@@ -6,7 +6,7 @@ import SwiftUI
import taler_swift
import SymLog
-// Will be called by the user tapping "Send Coins" in the balances list
+// Called when tapping "Send Coins" in the balances list
struct SendAmount: View {
private let symLog = SymLogV()
@@ -17,7 +17,7 @@ struct SendAmount: View {
@EnvironmentObject private var model: WalletModel
@State var peerPushCheck: CheckPeerPushDebitResponse? = nil
- @State private var expireDays: UInt = 0
+ @State private var expireDays: UInt = SEVENDAYS
private func fee(ppCheck: CheckPeerPushDebitResponse?) -> String {
do {
@@ -40,19 +40,18 @@ struct SendAmount: View {
let currencyField = CurrencyField(value: $centsToTransfer, currency:
currency)
let fee = fee(ppCheck: peerPushCheck)
-// ScrollViewReader { scrollView in
- VStack {
- let available = amountAvailable.readableDescription
- Text("Available: \(available)")
- .font(.title3)
- CurrencyInputView(currencyField: currencyField,
- title: String(localized: "Amount to send:"))
+ ScrollView {
+ VStack(alignment: .trailing) {
+ let available = amountAvailable.readableDescription
+ Text("Available: \(available)")
+ .font(.title3)
+ .padding(.bottom, 2)
+ CurrencyInputView(currencyField: currencyField,
+ title: String(localized: "Amount to send:"))
+ Text("+ \(fee) payment fee")
+ .foregroundColor(.red)
+ .padding(4)
- Text("+ \(fee) payment fee")
- .foregroundColor(.red)
- .padding(4)
-
- HStack {
let disabled = centsToTransfer == 0 // TODO: check
amountAvailable
NavigationLink(destination: LazyView {
@@ -61,16 +60,13 @@ struct SendAmount: View {
fee: fee,
summary: $summary,
expireDays: $expireDays)
-// { deactivateAction() }
}) {
Text("To another wallet")
- }
- .buttonStyle(TalerButtonStyle(type: .prominent))
- .disabled(disabled)
+ } .buttonStyle(TalerButtonStyle(type: .prominent))
+ .disabled(disabled)
+ Spacer()
}
- Spacer()
- }
-// }
+ }
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal)
.background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
@@ -83,15 +79,17 @@ struct SendAmount: View {
symLog.log("❗️Yikes SendAmount onDisappear")
}
.task(id: centsToTransfer) {
- let amount = Amount.amountFromCents(currency, centsToTransfer)
- do {
- let ppCheck = try await model.checkPeerPushDebitM(amount)
- peerPushCheck = ppCheck
+ if centsToTransfer > 0 {
+ let amount = Amount.amountFromCents(currency, centsToTransfer)
+ do {
+ let ppCheck = try await model.checkPeerPushDebitM(amount)
+ peerPushCheck = ppCheck
// TODO: set from exchange
// agePicker.setAges(ages: peerPushCheck?.ageRestrictionOptions)
- } catch { // TODO: error
- symLog.log(error.localizedDescription)
- peerPushCheck = nil
+ } catch { // TODO: error
+ symLog.log(error.localizedDescription)
+ peerPushCheck = nil
+ }
}
}
}
@@ -110,9 +108,9 @@ struct SendAmount_Container : View {
}
}
-struct SendAmount_Previews: PreviewProvider {
- static var previews: some View {
- SendAmount_Container()
- }
-}
+//struct SendAmount_Previews: PreviewProvider {
+// static var previews: some View {
+// SendAmount_Container()
+// }
+//}
#endif
diff --git a/TalerWallet1/Views/Peer2peer/SendNow.swift
b/TalerWallet1/Views/Peer2peer/SendDone.swift
similarity index 51%
rename from TalerWallet1/Views/Peer2peer/SendNow.swift
rename to TalerWallet1/Views/Peer2peer/SendDone.swift
index aba01b7..3abc1dd 100644
--- a/TalerWallet1/Views/Peer2peer/SendNow.swift
+++ b/TalerWallet1/Views/Peer2peer/SendDone.swift
@@ -6,13 +6,16 @@ import SwiftUI
import taler_swift
import SymLog
-struct SendNow: View {
+// Called when initiating a P2P transaction (Send coins or Send Invoice)
+struct SendDone: View {
private let symLog = SymLogV()
+ let navTitle = String(localized: "P2P Ready")
#if DEBUG
@AppStorage("developerMode") var developerMode: Bool = true
#else
@AppStorage("developerMode") var developerMode: Bool = false
#endif
+ @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
let amountToSend: Amount?
let amountToReceive: Amount?
@@ -21,40 +24,41 @@ struct SendNow: View {
@EnvironmentObject private var model: WalletModel
- @State var talerURI: String = ""
+ @State private var transactionId: String?
+
+ func reloadOneAction(_ transactionId: String) async throws -> Transaction {
+ return try await model.getTransactionByIdT(transactionId)
+ }
var body: some View {
+#if DEBUG
+ let _ = Self._printChanges()
+ let _ = symLog.vlog() // just to get the # to compare it with
.onAppear & onDisappear
+#endif
VStack {
- if talerURI.isEmpty {
- LoadingView(backButtonHidden: true)
+ if let transactionId {
+ TransactionDetailView(transactionId: transactionId,
+ reloadAction: reloadOneAction,
+ navTitle: navTitle,
+ doneAction:
ViewState.shared.popToRootView,
+ abortAction: nil,
+ deleteAction: nil,
+ failAction: nil,
+ suspendAction: nil,
+ resumeAction: nil)
+ .navigationBarBackButtonHidden(true)
+ .interactiveDismissDisabled() // can only use "Done"
button to dismiss
+ .navigationTitle(navTitle)
} else {
- QRCodeDetailView(talerURI: talerURI,
- incoming: amountToSend == nil)
- .padding()
- Text("The QR code can also be copied and shared from
Transactions later.")
- .fixedSize(horizontal: false, vertical: true)
- .font(.subheadline)
- .padding(.vertical, 20)
-
- Spacer()
- Button("Done") {
- withAnimation(){ ViewState.shared.popToRootView() }
- }
- .buttonStyle(TalerButtonStyle(type: .prominent))
- .padding()
-
+ WithdrawProgressView(message: "Loading...")
+ .navigationTitle(navTitle)
}
}
-// .frame(maxWidth: .infinity, maxHeight: .infinity, alignment:
.leading)
-// .padding(.horizontal)
- .interactiveDismissDisabled() // can only use "Done" button to
dismiss
- .navigationBarHidden(true) // no back button, no title
- .background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
+//
.background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
.task {
symLog.log(".task")
do {
- // generate talerURI
- var timestamp = developerMode ?
Timestamp.inSomeMinutes(expireDays > 20 ? (24*60)
+ let timestamp = developerMode ?
Timestamp.inSomeMinutes(expireDays > 20 ? (24*60)
:
expireDays > 5 ? 60 : 3)
:
Timestamp.inSomeDays(expireDays)
if let amountToSend {
@@ -63,18 +67,17 @@ struct SendNow: View {
purse_expiration: timestamp)
// TODO: user might choose baseURL
let response = try await model.initiatePeerPushDebitM(nil,
terms: terms)
- talerURI = response.talerUri
+ transactionId = response.transactionId
} else if let amountToReceive {
let terms = PeerContractTerms(amount: amountToReceive,
summary: summary,
purse_expiration: timestamp)
// TODO: user might choose baseURL
let response = try await
model.initiatePeerPullCreditM(nil, terms: terms)
- talerURI = response.talerUri
- } else { talerURI = "" }
+ transactionId = response.transactionId
+ } else { fatalError() }
} catch { // TODO: error
symLog.log(error.localizedDescription)
- talerURI = ""
}
} // task
}
@@ -83,11 +86,10 @@ struct SendNow: View {
struct SendNow_Previews: PreviewProvider {
static var previews: some View {
Group {
- SendNow(amountToSend: try! Amount(fromString: LONGCURRENCY +
":4.8"),
+ SendDone(amountToSend: try! Amount(fromString: LONGCURRENCY +
":4.8"),
amountToReceive: nil,
summary: "some purpose",
- expireDays: 0,
- talerURI:
"taler://pay-push/exchange.demo.taler.net/95ZG4D1AGFGZQ7CNQ1V49D3FT18HXKA6HQT4X3XME9YSJQVFQ520")
+ expireDays: 0)
}
}
}
diff --git a/TalerWallet1/Views/Peer2peer/SendPurpose.swift
b/TalerWallet1/Views/Peer2peer/SendPurpose.swift
index 50ee382..fa8202b 100644
--- a/TalerWallet1/Views/Peer2peer/SendPurpose.swift
+++ b/TalerWallet1/Views/Peer2peer/SendPurpose.swift
@@ -58,14 +58,14 @@ struct SendPurpose: View {
.font(.title3)
// TODO: compute max Expiration day from peerPushCheck to
disable 30 (and even 7)
- SelectDays(selected: $expireDays, maxExpiration: 35)
+ SelectDays(selected: $expireDays, maxExpiration: THIRTYDAYS)
.disabled(false)
.padding(.bottom)
let disabled = (expireDays == 0) || (summary.count < 1) //
TODO: check amountAvailable
NavigationLink(destination: LazyView {
- SendNow(amountToSend: amount,
+ SendDone(amountToSend: amount,
amountToReceive: nil,
summary: summary, expireDays: expireDays)
}) {
diff --git a/TalerWallet1/Views/Settings/Pending/PendingOpsListView.swift
b/TalerWallet1/Views/Settings/Pending/PendingOpsListView.swift
index 66691b6..2612eea 100644
--- a/TalerWallet1/Views/Settings/Pending/PendingOpsListView.swift
+++ b/TalerWallet1/Views/Settings/Pending/PendingOpsListView.swift
@@ -6,7 +6,6 @@ import SwiftUI
import SymLog
struct PendingOpsListView: View {
- private let symLog = SymLogV(0)
let navTitle = String(localized: "Pending")
@EnvironmentObject private var model: WalletModel
@@ -14,15 +13,10 @@ struct PendingOpsListView: View {
@State var pendingOperations: [PendingOperation] = []
var body: some View {
-#if DEBUG
- let _ = Self._printChanges()
- let _ = symLog.vlog() // just to get the # to compare it with
.onAppear & onDisappear
-#endif
let reloadAction = model.getPendingOperationsM
- Content(symLog: symLog, pendingOperations: $pendingOperations,
reloadAction: reloadAction)
+ Content(pendingOperations: $pendingOperations, reloadAction:
reloadAction)
.navigationTitle(navTitle)
.task {
- symLog.log(".task")
pendingOperations = await reloadAction()
}
}
@@ -30,29 +24,22 @@ struct PendingOpsListView: View {
// MARK: -
extension PendingOpsListView {
struct Content: View {
- let symLog: SymLogV?
@Binding var pendingOperations: [PendingOperation]
var reloadAction: () async -> [PendingOperation]
@AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
var body: some View {
-#if DEBUG
- let _ = Self._printChanges()
- let _ = symLog?.vlog() // just to get the # to compare it
with .onAppear & onDisappear
-#endif
- ScrollViewReader { scrollView in
+// ScrollViewReader { scrollView in
List(pendingOperations, id: \.self) { pendingOp in
PendingOpView(pendingOp: pendingOp)
}
.listStyle(myListStyle.style).anyView
- .navigationBarTitleDisplayMode(.large)
.onAppear() {
DebugViewC.shared.setViewID(VIEW_PENDING)
}
.refreshable {
- symLog?.log("refreshing")
pendingOperations = await reloadAction()
}
- }
+// }
}
}
}
diff --git a/TalerWallet1/Views/Settings/SettingsView.swift
b/TalerWallet1/Views/Settings/SettingsView.swift
index 8792071..ee7d4e6 100644
--- a/TalerWallet1/Views/Settings/SettingsView.swift
+++ b/TalerWallet1/Views/Settings/SettingsView.swift
@@ -42,6 +42,28 @@ struct SettingsView: View {
@State private var diagnosticModeEnabled =
UserDefaults.standard.bool(forKey: "diagnostic_mode_enabled")
#endif
@State private var showDevelopItems = false
+ @State private var showResetAlert: Bool = false
+ @State private var didReset: Bool = false
+
+ private var dismissAlertButton: some View {
+ Button("Cancel", role: .cancel) {
+ showResetAlert = false
+ }
+ }
+ private var resetButton: some View {
+ Button("Reset", role: .destructive) {
+ didReset = true
+ showResetAlert = false
+ Task {
+ symLog.log("❗️Reset wallet-core❗️")
+ do {
+ try await model.resetWalletCoreT()
+ } catch { // TODO: show error
+ symLog.log(error.localizedDescription)
+ }
+ }
+ }
+ }
var body: some View {
#if DEBUG
@@ -69,7 +91,7 @@ struct SettingsView: View {
}
if diagnosticModeEnabled {
SettingsToggle(name: String(localized: "Developer Mode"),
value: $developerMode,
- description: String(localized: "More
information intended for debugging")) {
+ description: String(localized: "More information
intended for debugging")) {
DebugViewC.shared.setViewID(VIEW_SETTINGS)
withAnimation { showDevelopItems = developerMode }
}
@@ -77,15 +99,17 @@ struct SettingsView: View {
NavigationLink { // whole row like in a
tableView
LazyView { PendingOpsListView() }
} label: {
- SettingsItem(name: String(localized: "Pending
Operations"), description: String(localized: "Exchange not yet ready...")) {}
+ SettingsItem(name: String(localized: "Pending
Operations"),
+ description: String(localized: "Exchange not
yet ready...")) {}
}
SettingsToggle(name: String(localized: "Set 2 seconds
delay"), value: $developDelay,
- description: String(localized: "After
each wallet-core action"))
+ description: String(localized: "After each
wallet-core action"))
.onChange(of: developDelay, perform: { developDelay in
walletCore.developDelay = developDelay
})
- SettingsItem(name: String(localized: "Withdraw
\(DEMOCURRENCY)"), description: String(localized: "Get money for testing")) {
+ SettingsItem(name: String(localized: "Withdraw
\(DEMOCURRENCY)"),
+ description: String(localized: "Get money for
testing")) {
Button("Withdraw") {
withDrawDisabled = true // don't run twice
Task {
@@ -100,7 +124,8 @@ struct SettingsView: View {
.buttonStyle(.bordered)
.disabled(withDrawDisabled)
}
- SettingsItem(name: String(localized: "Withdraw
\(TESTCURRENCY)"), description: String(localized: "Get money for testing")) {
+ SettingsItem(name: String(localized: "Withdraw
\(TESTCURRENCY)"),
+ description: String(localized: "Get money for
testing")) {
Button("Withdraw") {
withDrawDisabled = true // don't run twice
Task {
@@ -116,7 +141,7 @@ struct SettingsView: View {
.disabled(withDrawDisabled)
}
SettingsItem(name: String(localized: "Run Integration
Test"),
- description: String(localized: "Perform
basic test transactions")) {
+ description: String(localized: "Perform basic
test transactions")) {
Button("Demo 1") {
checkDisabled = true // don't run twice
Task {
@@ -132,23 +157,15 @@ struct SettingsView: View {
.disabled(checkDisabled)
}
SettingsItem(name: String(localized: "Run Integration
Test"),
- description: String(localized: "Perform
basic test transactions")) {
+ description: String(localized: "Perform basic
test transactions")) {
Button("Test 1") {
checkDisabled = true // don't run twice
- Task {
- symLog.log("running integration test on
test")
- do {
- try await
model.runIntegrationTestM(newVersion: false, test: true)
- } catch { // TODO: show error
- symLog.log(error.localizedDescription)
- }
- }
}
.buttonStyle(.bordered)
.disabled(checkDisabled)
}
SettingsItem(name: String(localized: "Run Integration
Test V2"),
- description: String(localized: "Perform
more test transactions")) {
+ description: String(localized: "Perform more
test transactions")) {
Button("Demo 2") {
checkDisabled = true // don't run twice
Task {
@@ -164,7 +181,7 @@ struct SettingsView: View {
.disabled(checkDisabled)
}
SettingsItem(name: String(localized: "Run Integration
Test V2"),
- description: String(localized: "Perform
more test transactions")) {
+ description: String(localized: "Perform more
test transactions")) {
Button("Test 2") {
checkDisabled = true // don't run twice
Task {
@@ -180,7 +197,7 @@ struct SettingsView: View {
.disabled(checkDisabled)
}
SettingsItem(name: String(localized: "Save Logfile"),
- description: String(localized: "Help
debugging wallet-core")) {
+ description: String(localized: "Help debugging
wallet-core")) {
Button("Save") {
symLog.log("Saving Log")
// FIXME: Save Logfile
@@ -188,6 +205,14 @@ struct SettingsView: View {
.buttonStyle(.bordered)
.disabled(true)
}
+ SettingsItem(name: String(localized: "Reset Wallet"),
+ description: String(localized: "Throw away all
your money")) {
+ Button("Reset") {
+ showResetAlert = true
+ }
+ .buttonStyle(.bordered)
+ .disabled(didReset)
+ }
}
}
@@ -210,7 +235,7 @@ struct SettingsView: View {
SettingsItem(name: "Used Bank") {
Text(verbatim: "\(walletCore.versionInfo!.bank)")
}
- }
+ } // App version info
}
.listStyle(myListStyle.style).anyView
}
@@ -220,6 +245,12 @@ struct SettingsView: View {
showDevelopItems = developerMode
DebugViewC.shared.setViewID(VIEW_SETTINGS)
}
+ .alert("Reset Wallet",
+ 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.") })
+
#if !DEBUG
.onReceive(
NotificationCenter.default
diff --git a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pAcceptDone.swift
b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pAcceptDone.swift
index 6eb706d..264c624 100644
--- a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pAcceptDone.swift
+++ b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pAcceptDone.swift
@@ -6,6 +6,7 @@ import SwiftUI
import taler_swift
import SymLog
+// Called when accepting a scanned P2P transaction (Receive coins or Pay
Invoice)
struct P2pAcceptDone: View {
private let symLog = SymLogV()
@@ -26,33 +27,38 @@ struct P2pAcceptDone: View {
let _ = Self._printChanges()
let _ = symLog.vlog() // just to get the # to compare it with
.onAppear & onDisappear
#endif
- let navTitle = incoming ? String(localized: "Received P2P")
- : String(localized: "Paid P2P")
- ScrollViewReader { scrollView in
- VStack {
- TransactionDetailView(transactionId: transactionId,
- reloadAction: reloadOneAction,
- doneAction: { dismissTop() })
+ let navTitle = incoming ? String(localized: "Received P2P", comment:
"Title, short")
+ : String(localized: "Paid P2P", comment:
"Title, short")
+ TransactionDetailView(transactionId: transactionId,
+ reloadAction: reloadOneAction,
+ navTitle: navTitle,
+ doneAction: { dismissTop() },
+ abortAction: nil,
+ deleteAction: nil,
+ failAction: nil,
+ suspendAction: nil,
+ resumeAction: nil)
.navigationBarBackButtonHidden(true)
.interactiveDismissDisabled() // can only use "Done"
button to dismiss
.navigationTitle(navTitle)
- }.onAppear() {
- symLog.log("onAppear")
- DebugViewC.shared.setSheetID(SHEET_RCV_P2P_ACCEPT)
- }.task {
- do {
- if incoming {
- _ = try await model.acceptPeerPushCreditM(transactionId)
- } else {
- _ = try await model.confirmPeerPullDebitM(transactionId)
+ .onAppear() {
+ symLog.log("onAppear")
+ DebugViewC.shared.setSheetID(incoming ? SHEET_RCV_P2P_ACCEPT
+ : SHEET_PAY_P2P_ACCEPT)
+ }
+ .task {
+ do {
+ if incoming {
+ _ = try await
model.acceptPeerPushCreditM(transactionId)
+ } else {
+ _ = try await
model.confirmPeerPullDebitM(transactionId)
+ }
+ finished = true
+ } catch { // TODO: error
+ symLog.log(error.localizedDescription)
+ controller.playSound(0)
}
- finished = true
- } catch { // TODO: error
- symLog.log(error.localizedDescription)
- controller.playSound(0)
}
- }
- }
}
}
// MARK: -
diff --git a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift
b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift
index 89a6502..93d8eb0 100644
--- a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift
+++ b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift
@@ -10,7 +10,7 @@ import SymLog
// from another user's SendInvoice. We show the P2P details.
struct P2pPayURIView: View {
private let symLog = SymLogV()
- let navTitle = String(localized: "Pay P2P Invoice")
+ let navTitle = String(localized: "Pay P2P")
// the scanned URL
let url: URL
diff --git a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift
b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift
index c4f4301..d38d73b 100644
--- a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift
+++ b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift
@@ -10,7 +10,7 @@ import SymLog
// from another user's SendCoins. We show the P2P details - but first the ToS
must be accepted.
struct P2pReceiveURIView: View {
private let symLog = SymLogV()
- let navTitle = String(localized: "Accept P2P Receive")
+ let navTitle = String(localized: "P2P Receive")
@AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
// the scanned URL
@@ -43,16 +43,19 @@ struct P2pReceiveURIView: View {
P2pAcceptDone(transactionId:
peerPushCreditResponse.transactionId,
incoming: true)
}) {
- Text("Accept Withdrawal") // SHEET_WITHDRAW_ACCEPT
+ Text("Accept P2P Receive") // SHEET_RCV_P2P_ACCEPT
}.buttonStyle(TalerButtonStyle(type: .prominent))
.padding()
} else {
+ Text("You must accept the Terms of Service first before
you can receive electronic cash to your wallet.")
+ .multilineTextAlignment(.leading)
+ .padding()
NavigationLink(destination: LazyView {
WithdrawTOSView(exchangeBaseUrl: nil,
viewID: SHEET_RCV_P2P_TOS,
acceptAction: nil) // pop
back to here
}) {
- Text("Check Terms of Service")
+ Text("Read Terms of Service")
}.buttonStyle(TalerButtonStyle(type: .prominent))
.padding()
}
diff --git a/TalerWallet1/Views/Sheets/Sheet.swift
b/TalerWallet1/Views/Sheets/Sheet.swift
index 43b1895..abc564b 100644
--- a/TalerWallet1/Views/Sheets/Sheet.swift
+++ b/TalerWallet1/Views/Sheets/Sheet.swift
@@ -28,13 +28,15 @@ struct Sheet: View {
NavigationView {
sheetView
.navigationBarItems(leading: cancelButton)
+ .navigationBarTitleDisplayMode(.automatic)
.background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
- }
+ }.navigationViewStyle(.stack)
.overlay(alignment: .top) {
// Show the viewID on top of the sheet's NavigationView
Text(idString)
.font(.caption2)
.foregroundColor(.purple)
+ .monospacedDigit()
.edgesIgnoringSafeArea(.top)
.id("sheetID")
}
diff --git a/TalerWallet1/Views/Sheets/URLSheet.swift
b/TalerWallet1/Views/Sheets/URLSheet.swift
index 723480f..4a3cacd 100644
--- a/TalerWallet1/Views/Sheets/URLSheet.swift
+++ b/TalerWallet1/Views/Sheets/URLSheet.swift
@@ -7,40 +7,31 @@ import SymLog
struct URLSheet: View {
private let symLog = SymLogV()
- let navTitle = String(localized: "Examining URL")
+ let navTitle = String(localized: "Checking Link")
var urlToOpen: URL
@EnvironmentObject private var controller: Controller
- @State private var urlCommand: UrlCommand? = nil
-
var body: some View {
+ let urlCommand = controller.openURL(urlToOpen)
+
Group {
- if let urlCommand {
- switch urlCommand {
- case .withdraw:
- WithdrawURIView(url: urlToOpen)
- case .pay:
- PaymentURIView(url: urlToOpen)
- case .payPull:
- P2pPayURIView(url: urlToOpen)
- case .payPush:
- P2pReceiveURIView(url: urlToOpen)
- case .unknown:
+ switch urlCommand {
+ case .withdraw:
+ WithdrawURIView(url: urlToOpen)
+ case .pay:
+ PaymentURIView(url: urlToOpen)
+ case .payPull:
+ P2pPayURIView(url: urlToOpen)
+ case .payPush:
+ P2pReceiveURIView(url: urlToOpen)
+ case .unknown: // Error view
+ VStack {
Text("unknown command")
- }
- } else {
- VStack { // Error view
- Spacer()
- Text(controller.messageForSheet ??
urlToOpen.absoluteString)
- .font(.title)
- Spacer()
- Spacer()
- }
- .navigationTitle(navTitle)
+ .font(.title)
+ Text(controller.messageForSheet ??
urlToOpen.absoluteString)
+ }
+ .navigationTitle(navTitle)
}
- }.task {
- symLog.log(urlToOpen)
- urlCommand = controller.openURL(urlToOpen)
}
}
}
diff --git a/TalerWallet1/Views/Transactions/ManualDetails.swift
b/TalerWallet1/Views/Transactions/ManualDetails.swift
index fd6db87..6663ef1 100644
--- a/TalerWallet1/Views/Transactions/ManualDetails.swift
+++ b/TalerWallet1/Views/Transactions/ManualDetails.swift
@@ -14,42 +14,42 @@ struct ManualDetails: View {
let payURL = URL(string: payto)
let iban = payURL?.iban ?? "unknown IBAN"
let amount = common.amountRaw.readableDescription
- Text("Make a wire transfer of \(amount) to:")
+ Text("From your regular bank account, make a wire transfer of
\(amount) to:")
+ .multilineTextAlignment(.leading)
.listRowSeparator(.hidden)
HStack {
Text(iban)
+ .monospacedDigit()
Spacer()
CopyButton(textToCopy: iban, vertical: true)
- .accessibilityLabel("Copy IBAN")
+ .accessibilityLabel("Copy the IBAN")
.disabled(false)
} .padding(.leading)
.padding(.vertical, -8)
.listRowSeparator(.hidden)
- Text("and use the transaction subject:")
+ Text("with the code below as subject to receive the money in this
wallet:")
+ .multilineTextAlignment(.leading)
.listRowSeparator(.hidden)
HStack {
Text(details.reservePub)
- .accessibilityLabel("Taler cryptocode")
+ .monospacedDigit()
+ .accessibilityLabel("Cryptocode")
Spacer()
CopyButton(textToCopy: details.reservePub, vertical: true)
- .accessibilityLabel("Copy subject")
+ .accessibilityLabel("Copy the cryptocode")
.disabled(false)
} .padding(.leading)
- .padding(.vertical, -8)
.listRowSeparator(.hidden)
HStack {
+ Text(verbatim: "|") // only reason for this
leading-aligned text is to get a nice full length listRowSeparator
+ .accessibilityHidden(true)
+ .foregroundColor(Color.clear)
Spacer()
ShareButton(textToShare: payto)
- .accessibilityLabel("Share PayTo URL")
+ .accessibilityLabel("Share the PayTo URL")
.disabled(false)
Spacer()
- } .listRowSeparator(.hidden)
- Text(verbatim: "PayTo URL") // the only reason for this
leading-aligned text is to get a nice full lenght listRowSeparator
- .font(.footnote)
- .foregroundColor(Color.yellow) // clear
- .padding(.vertical, -8)
- .listRowSeparator(.automatic)
- .accessibilityHidden(true)
+ } .listRowSeparator(.automatic)
}
}
}
diff --git a/TalerWallet1/Views/Transactions/ThreeAmounts.swift
b/TalerWallet1/Views/Transactions/ThreeAmounts.swift
index 8d85c04..8f2287a 100644
--- a/TalerWallet1/Views/Transactions/ThreeAmounts.swift
+++ b/TalerWallet1/Views/Transactions/ThreeAmounts.swift
@@ -19,20 +19,21 @@ struct ThreeAmountsSheet: View {
let incoming = common.incoming()
let pending = (common.txState.major == TransactionMajorState.pending)
- let defaultBottomTitle = incoming ? (pending ? "Pending coins to
obtain:" : "Obtained coins:")
- : "Paid coins:"
+ let defaultBottomTitle = incoming ? (pending ? String(localized:
"Pending amount to obtain:")
+ : String(localized:
"Obtained amount:") )
+ : String(localized: "Paid
amount:")
ThreeAmountsView(topTitle: topTitle, topAmount: raw, fee: fee,
bottomTitle: bottomTitle ?? defaultBottomTitle,
bottomAmount: effective,
large: large, pending: pending, incoming: incoming,
baseURL: baseURL,
- status: common.txState.major.rawValue)
+ status: common.txState.major.localizedState)
}
}
// MARK: -
struct ThreeAmountsView: View {
var topTitle: String
var topAmount: Amount
- var fee: Amount
+ var fee: Amount?
var bottomTitle: String
var bottomAmount: Amount
let large: Bool
@@ -54,11 +55,13 @@ struct ThreeAmountsView: View {
color: labelColor,
large: large)
.padding(.bottom, 4)
- AmountView(title: "Exchange fee:",
- value: feeSign + fee.readableDescription,
- color: fee.isZero ? labelColor : feeColor,
- large: false)
+ if let fee {
+ AmountView(title: "Exchange fee:",
+ value: feeSign + fee.readableDescription,
+ color: fee.isZero ? labelColor : feeColor,
+ large: false)
.padding(.bottom, 4)
+ }
AmountView(title: bottomTitle,
value: bottomAmount.readableDescription,
color: foreColor,
@@ -72,8 +75,8 @@ struct ThreeAmountsView: View {
Spacer()
Text(baseURL.trimURL())
.multilineTextAlignment(.center)
- .font(large ? .title : .title2)
- // .fontWeight(large ? .medium
: .regular) // @available(iOS 16.0, *)
+ .font(large ? .title2 : .title3)
+// .fontWeight(large ? .medium : .regular) //
@available(iOS 16.0, *)
.foregroundColor(labelColor)
Spacer()
}
@@ -82,13 +85,6 @@ struct ThreeAmountsView: View {
.frame(maxWidth: .infinity, alignment: .leading)
.listRowSeparator(.hidden)
}
- if let status {
- HStack {
- Spacer()
- Text("Status: \(status)")
- .font(.title2)
- }.padding()
- }
}
}
}
diff --git a/TalerWallet1/Views/Transactions/TransactionDetailView.swift
b/TalerWallet1/Views/Transactions/TransactionDetailView.swift
index 0c87221..bb2f404 100644
--- a/TalerWallet1/Views/Transactions/TransactionDetailView.swift
+++ b/TalerWallet1/Views/Transactions/TransactionDetailView.swift
@@ -30,18 +30,20 @@ struct TransactionDetailView: View {
@AppStorage("developerMode") var developerMode: Bool = false
#endif
- var transactionId: String
+ let transactionId: String
+ let reloadAction: ((_ transactionId: String) async throws -> Transaction)
+
+ let navTitle: String?
+ let doneAction: (() -> Void)?
+ let abortAction: ((_ transactionId: String) async throws -> Void)?
+ let deleteAction: ((_ transactionId: String) async throws -> Void)?
+ let failAction: ((_ transactionId: String) async throws -> Void)?
+ let suspendAction: ((_ transactionId: String) async throws -> Void)?
+ let resumeAction: ((_ transactionId: String) async throws -> Void)?
+
@State var transaction: Transaction = Transaction(dummyCurrency:
DEMOCURRENCY)
@State var viewId = UUID()
- var reloadAction: ((_ transactionId: String) async throws -> Transaction)
- var abortAction: ((_ transactionId: String) async throws -> Void)?
- var deleteAction: ((_ transactionId: String) async throws -> Void)?
- var failAction: ((_ transactionId: String) async throws -> Void)?
- var doneAction: (() -> Void)?
- var suspendAction: ((_ transactionId: String) async throws -> Void)?
- var resumeAction: ((_ transactionId: String) async throws -> Void)?
-
var body: some View {
#if DEBUG
let _ = Self._printChanges()
@@ -51,7 +53,7 @@ struct TransactionDetailView: View {
let pending = transaction.isPending
let dateString = TalerDater.dateString(from: common.timestamp)
let localizedType = transaction.localizedType
- let navTitle = pending ? String(localized: "Pending \(localizedType)")
+ let navTitle2 = pending ? String(localized: "Pending")
: localizedType
Group {
List {
@@ -67,8 +69,17 @@ struct TransactionDetailView: View {
} // Suspend + Resume buttons
Text(dateString)
.font(.title2)
-// .listRowSeparator(.hidden)
- SwitchCase(transaction: $transaction)
+ .listRowSeparator(.hidden)
+ HStack {
+ Text(verbatim: "|") // only reason for this
leading-aligned text is to get a nice full length listRowSeparator
+ .font(.title2)
+ .accessibilityHidden(true)
+ .foregroundColor(Color.clear)
+ Spacer()
+ Text("Status: \(common.txState.major.localizedState)")
+ .font(.title2)
+ } .listRowSeparator(.automatic)
+ SwitchCase(transaction: $transaction, hasDone: doneAction !=
nil)
if transaction.isAbortable { if let abortAction {
TransactionButton(transactionId: common.transactionId,
@@ -82,9 +93,6 @@ struct TransactionDetailView: View {
TransactionButton(transactionId: common.transactionId,
command: .delete, action: deleteAction)
} } // Delete button
-// if let doneAction {
-// DoneButton(doneAction: doneAction)
-// } // Done button
}.id(viewId) // change viewId to enforce a draw update
.listStyle(myListStyle.style).anyView
.safeAreaInset(edge: .bottom) {
@@ -103,6 +111,9 @@ struct TransactionDetailView: View {
if newMajor == .done {
symLog.log("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")
+ 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
@@ -135,7 +146,7 @@ struct TransactionDetailView: View {
symLog.log(notification.userInfo as Any)
}
}
- .navigationTitle(navTitle)
+ .navigationTitle(navTitle ?? navTitle2)
.task {
do {
symLog.log("task - load transaction")
@@ -159,6 +170,7 @@ struct TransactionDetailView: View {
//extension TransactionDetail {
struct SwitchCase: View {
@Binding var transaction: Transaction
+ let hasDone: Bool
var body: some View {
let common = transaction.common
@@ -180,9 +192,10 @@ struct TransactionDetailView: View {
if !confirmed {
if let confirmationUrl =
withdrawalDetails.bankConfirmationUrl {
if let destination = URL(string:
confirmationUrl) {
- VStack { // Show Hint that
User should Confirm on bank website
+ VStack(alignment: .leading) {
// Show Hint that User should Confirm on bank website
Text("Waiting for bank
confirmation")
-
.multilineTextAlignment(.leading)
+ .fixedSize(horizontal:
false, vertical: true) // wrap in scrollview
+
.multilineTextAlignment(.leading) // otherwise
.listRowSeparator(.hidden)
Link("Confirm with bank",
destination: destination)
.buttonStyle(TalerButtonStyle(type: .prominent, narrow: false, aligned:
.center))
@@ -226,10 +239,16 @@ struct TransactionDetailView: View {
.lineLimit(4)
.padding(.bottom)
// TODO: isSendCoins should show QR only while not
expired
- if pending || transaction.isSendCoins {
+ if pending {
QRCodeDetails(transaction: transaction)
+ if hasDone {
+ Text("QR code and link can also be scanned or
copied / shared from Transactions later.")
+ .multilineTextAlignment(.leading)
+ .font(.subheadline)
+ .padding(.top)
+ }
}
- ThreeAmountsSheet(common: common, topTitle:
String(localized: "Peer to Peer:"),
+ ThreeAmountsSheet(common: common, topTitle:
transaction.localizedType,
baseURL: details.exchangeBaseUrl,
large: false)
} // switch
} // Group
@@ -245,7 +264,8 @@ struct TransactionDetailView: View {
if let talerURI = details[TALERURI] {
if talerURI.count > 10 {
QRCodeDetailView(talerURI: talerURI,
- incoming: transaction.isP2pIncoming)
+ incoming: transaction.isP2pIncoming,
+ amount:
transaction.common.amountRaw)
}
}
} else if keys.contains(EXCHANGEBASEURL) {
diff --git a/TalerWallet1/Views/Transactions/TransactionRowView.swift
b/TalerWallet1/Views/Transactions/TransactionRowView.swift
index 1966234..cf57414 100644
--- a/TalerWallet1/Views/Transactions/TransactionRowView.swift
+++ b/TalerWallet1/Views/Transactions/TransactionRowView.swift
@@ -53,6 +53,7 @@ struct TransactionRowView: View {
Text(valueStr)
.font(.title)
.foregroundColor(foreColor)
+ .monospacedDigit()
}
}
.accessibilityElement(children: .combine)
diff --git a/TalerWallet1/Views/Transactions/TransactionsListView.swift
b/TalerWallet1/Views/Transactions/TransactionsListView.swift
index d5a4f3c..16ce785 100644
--- a/TalerWallet1/Views/Transactions/TransactionsListView.swift
+++ b/TalerWallet1/Views/Transactions/TransactionsListView.swift
@@ -16,131 +16,101 @@ struct TransactionsListView: View {
let reloadAllAction: () async -> ()
let reloadOneAction: ((_ transactionId: String) async throws ->
Transaction)
+ @State private var viewId = UUID()
+ @State private var upAction: () -> Void = {}
+ @State private var downAction: () -> Void = {}
var body: some View {
#if DEBUG
let _ = Self._printChanges()
let _ = symLog.vlog() // just to get the # to compare it with
.onAppear & onDisappear
#endif
let count = transactions.count
- // TODO: Unlock the power of grammatical agreement
-// let title = AttributedString(localized: "^[\(count) Ticket](inflect:
true)")
-// let title: String = "\(count) \(navTitle)"
- Content(symLog: symLog,
- currency: currency,
- transactions: transactions,
- showUpDown: showUpDown,
- myListStyle: $myListStyle,
- reloadAllAction: reloadAllAction,
- reloadOneAction: reloadOneAction)
-// .navigationTitle(title)
- .navigationTitle(navTitle)
- .navigationBarTitleDisplayMode(.large) // .inline
- .onAppear {
- DebugViewC.shared.setViewID(VIEW_TRANSACTIONLIST)
+ ScrollViewReader { scrollView in
+ List {
+ TransactionsRowsView(symLog: symLog,
+ currency: currency,
+ transactions: transactions,
+// reloadAllAction: reloadAllAction,
+ reloadOneAction: reloadOneAction)
}
- .task {
- symLog.log(".task ")
+ .id(viewId)
+ .listStyle(myListStyle.style).anyView
+ .refreshable {
+ symLog.log("refreshing")
await reloadAllAction()
}
+ .navigationBarItems(trailing: HStack {
+ if showUpDown {
+ ArrowUpButton(action: upAction)
+ ArrowDownButton(action: downAction)
+ } else {
+ EmptyView()
+ }
+ })
+ .onAppear {
+ if showUpDown {
+ upAction = {
+ withAnimation { scrollView.scrollTo(0) }
+ }
+ downAction = {
+ withAnimation { scrollView.scrollTo(transactions.count
- 1) }
+ }
+// downAction()
+ }
+ }
+ } // ScrollView
+ .navigationTitle(navTitle)
+ .task {
+ symLog.log(".task ")
+ await reloadAllAction()
+ }
+ .overlay {
+ if transactions.isEmpty {
+ TransactionsEmptyView(currency: currency)
+ }
+ }
+ .onAppear {
+ DebugViewC.shared.setViewID(VIEW_TRANSACTIONLIST)
+ }
}
}
// MARK: -
-extension TransactionsListView {
- struct Content: View {
- let symLog: SymLogV?
- let currency: String
- let transactions: [Transaction]
- let showUpDown: Bool
- @Binding var myListStyle: MyListStyle
- let reloadAllAction: () async -> ()
- let reloadOneAction: ((_ transactionId: String) async throws ->
Transaction)
-
- @EnvironmentObject private var model: WalletModel
-
- @State private var upAction: () -> Void = {}
- @State private var downAction: () -> Void = {}
-
-// func removeItems(at offsets: IndexSet) {
-// let transactions = model.transactions
-// var idsToDelete: [String] = []
-// for n in offsets { // save IDs of transactions
-// let common = transactions[n].common
-// idsToDelete.append(common.transactionId)
-// }
-// // then remove items from the list model (and the view)
-// model.transactions.remove(atOffsets: offsets)
-// // finally tell wallet-core to delete the saved IDs
-// Task { // delete this transaction from wallet-core
-// for transactionId in idsToDelete {
-// do {
-// try await deleteAction(transactionId)
-// symLog?.log("deleted \(transactionId)")
-// } catch { // TODO: error
-// symLog?.log(error.localizedDescription)
-// }
-// }
-// }
-// }
+// used by TransactionsListView, and by Balances to show the last 3
transactions
+struct TransactionsRowsView: View {
+ let symLog: SymLogV?
+ let currency: String
+ let transactions: [Transaction]
+// let reloadAllAction: () async -> ()
+ let reloadOneAction: ((_ transactionId: String) async throws ->
Transaction)
- @State var viewId = UUID()
- var body: some View {
+ @EnvironmentObject private var model: WalletModel
+ var body: some View {
#if DEBUG
- let _ = Self._printChanges()
- let _ = symLog?.vlog() // just to get the # to compare it
with .onAppear & onDisappear
+ let _ = Self._printChanges()
+ let _ = symLog?.vlog() // just to get the # to compare it with
.onAppear & onDisappear
#endif
- let abortAction = model.abortTransaction
- let deleteAction = model.deleteTransaction
- let failAction = model.failTransaction
- let suspendAction = model.suspendTransaction
- let resumeAction = model.resumeTransaction
- ScrollViewReader { scrollView in
- List {
- ForEach(Array(zip(transactions.indices, transactions)),
id: \.1) { index, transaction in
- NavigationLink { LazyView { // whole row like
in a tableView
- // pending may not be deleted, but only aborted
- TransactionDetailView(transactionId:
transaction.id,
- reloadAction: reloadOneAction,
- abortAction: abortAction,
- deleteAction: deleteAction,
- failAction: failAction,
- suspendAction: suspendAction,
- resumeAction: resumeAction)
- }} label: {
- TransactionRowView(transaction: transaction)
- }
- }
-// .onDelete(perform: removeItems) // delete this row
from the list
- }.id(viewId)
- .listStyle(myListStyle.style).anyView
- .refreshable {
- symLog?.log("refreshing")
- await reloadAllAction()
- }
- .onAppear {
- if showUpDown {
- upAction = { withAnimation { scrollView.scrollTo(0) }}
- downAction = { withAnimation {
scrollView.scrollTo(transactions.count - 1) }}
- downAction()
- }
- }
- .overlay {
- if transactions.isEmpty {
- TransactionsEmptyView(currency: currency)
- }
+ let abortAction = model.abortTransaction
+ let deleteAction = model.deleteTransaction
+ let failAction = model.failTransaction
+ let suspendAction = model.suspendTransaction
+ let resumeAction = model.resumeTransaction
+ ForEach(Array(zip(transactions.indices, transactions)), id: \.1) {
index, transaction in
+ NavigationLink {
+ LazyView {
+ TransactionDetailView(transactionId: transaction.id,
+ reloadAction: reloadOneAction,
+ navTitle: nil,
+ doneAction: nil,
+ abortAction: abortAction,
+ deleteAction: deleteAction,
+ failAction: failAction,
+ suspendAction: suspendAction,
+ resumeAction: resumeAction)
}
+ } label: {
+ TransactionRowView(transaction: transaction)
}
- .navigationBarItems(trailing: HStack {
- EmptyView()
- if showUpDown {
- ArrowUpButton(action: upAction)
- ArrowDownButton(action: downAction)
- }
- })
+ .id(Int(index))
}
}
}
-//struct TransactionsView_Previews: PreviewProvider {
-// static var previews: some View {
-// TransactionsView()
-// }
-//}
diff --git a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptDone.swift
b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptDone.swift
index 1a802f1..ec64275 100644
--- a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptDone.swift
+++ b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawAcceptDone.swift
@@ -27,12 +27,17 @@ struct WithdrawAcceptDone: View {
let _ = Self._printChanges()
let _ = symLog.vlog() // just to get the # to compare it with
.onAppear & onDisappear
#endif
- ScrollViewReader { scrollView in
- VStack {
+ Group {
if let transactionId {
TransactionDetailView(transactionId: transactionId,
reloadAction: reloadOneAction,
- doneAction: { dismissTop() })
+ navTitle: navTitle,
+ doneAction: { dismissTop() },
+ abortAction: nil,
+ deleteAction: nil,
+ failAction: nil,
+ suspendAction: nil,
+ resumeAction: nil)
.navigationBarBackButtonHidden(true)
.interactiveDismissDisabled() // can only use "Done"
button to dismiss
.navigationTitle(navTitle)
@@ -56,7 +61,6 @@ struct WithdrawAcceptDone: View {
controller.playSound(0)
}
}
- }
}
}
// MARK: -
diff --git a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawTOSView.swift
b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawTOSView.swift
index e7a4a53..41b7839 100644
--- a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawTOSView.swift
+++ b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawTOSView.swift
@@ -39,7 +39,6 @@ struct WithdrawTOSView: View {
}
}
}
- .navigationBarTitleDisplayMode(.large) // .inline
.navigationTitle(navTitle)
.overlay {
if exchangeTOS == nil {
@@ -91,8 +90,18 @@ extension WithdrawTOSView {
let term2 = term1.replacingOccurrences(of: "\n" ,
with: " ") // remove all other linebreaks
let term3 = term2.replacingOccurrences(of: " ====",
with: "\n====") // add them back for underscoring
let term4 = term3.replacingOccurrences(of: " ----",
with: "\n----") // special for "Highlights:"
- Section {
- Text(term4)
+ let term5 = term4.replacingOccurrences(of: " ****",
with: "\n****") // special for "Terms of Service:"
+// Text("term0")
+ if #available(iOS 16.0, *) {
+ Section {
+ Text(term5)
+ .font(.footnote)
+ .foregroundColor(Color(UIColor.label))
+ }
+ } else {
+ Text(term5)
+ .font(.footnote)
+ .foregroundColor(Color(UIColor.label))
}
} else {
Section {
@@ -100,7 +109,7 @@ extension WithdrawTOSView {
}
}
}.safeAreaInset(edge: .bottom) {
- Button(String(localized: "Accept ToS"), action:
acceptAction)
+ Button(String(localized: "Accept Terms of Service",
comment: "Button"), action: acceptAction)
.buttonStyle(TalerButtonStyle(type: .prominent))
.padding(.horizontal)
}
diff --git a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawURIView.swift
b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawURIView.swift
index e86a472..ec29e4c 100644
--- a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawURIView.swift
+++ b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawURIView.swift
@@ -11,7 +11,7 @@ import SymLog
// after the user confirmed the withdrawal, we remind them to return to the
bank website to confirm there, too
struct WithdrawURIView: View {
private let symLog = SymLogV()
- let navTitle = String(localized: "Accept Withdrawal")
+ let navTitle = String(localized: "Withdrawal")
// the URL from the bank website
let url: URL
@@ -56,12 +56,15 @@ struct WithdrawURIView: View {
}.buttonStyle(TalerButtonStyle(type: .prominent))
.padding()
} else {
+ Text("You must accept the Terms of Service first before
you can withdraw electronic cash to your wallet.")
+ .multilineTextAlignment(.leading)
+ .padding()
NavigationLink(destination: LazyView {
WithdrawTOSView(exchangeBaseUrl: exchangeBaseUrl,
viewID: SHEET_WITHDRAW_TOS,
acceptAction: nil) // pop
back to here
}) {
- Text("Check Terms of Service") // VIEW_WITHDRAW_TOS
+ Text("Read Terms of Service") // VIEW_WITHDRAW_TOS
}.buttonStyle(TalerButtonStyle(type: .prominent))
.padding()
}
diff --git a/TestFlight/WhatToTest.en-US.txt b/TestFlight/WhatToTest.en-US.txt
index a83b1b4..6b0aa3b 100644
--- a/TestFlight/WhatToTest.en-US.txt
+++ b/TestFlight/WhatToTest.en-US.txt
@@ -1,7 +1,29 @@
+Version 0.9.3 (16)
+
+• Switch on Developer Mode in Settings, then
+• Run Integration Test (Demo 1), then immediately switch back to Balances
+• (repeat with Demo 2)
+
+- Terms of Service more self-explaining (check this before running the
integration test)
+- Expiration pre-selected (middle button) in P2P
+- Transaction details: Status field on top for better recognition
+- Balances shows the last 3 transactions
+- QR screen no longer vanishes immediately (P2P)
+
+
+Version 0.9.3 (15)
+
+• New Feature: Reset wallet (Throw away all your coins)
+• Insufficient Balance detected when trying to pay sth.
+
+- Integration Test works again (was broken in 10..14)
+
+
Version 0.9.3 (14)
- ToS formatted with markdown (if the exchange supports this)
+- Payment in the shop works again (was broken in 12 + 13)
Version 0.9.3 (13)
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [taler-taler-ios] branch master updated (ad57348 -> dbf44d6),
gnunet <=
- [taler-taler-ios] 01/35: Test notes, gnunet, 2023/07/27
- [taler-taler-ios] 03/35: logging, gnunet, 2023/07/27
- [taler-taler-ios] 05/35: insufficientBalance, gnunet, 2023/07/27
- [taler-taler-ios] 02/35: navigationBarTitleDisplayMode, gnunet, 2023/07/27
- [taler-taler-ios] 06/35: no need to call urlCommand async, gnunet, 2023/07/27
- [taler-taler-ios] 10/35: Atkinson Hyperlegible, gnunet, 2023/07/27
- [taler-taler-ios] 09/35: localizations, wording, gnunet, 2023/07/27
- [taler-taler-ios] 08/35: iOS 15: show ToS, gnunet, 2023/07/27
- [taler-taler-ios] 11/35: monospacedDigit, gnunet, 2023/07/27
- [taler-taler-ios] 07/35: iOS: bump version to 0.9.3 (15), gnunet, 2023/07/27