diff --git a/TalerCommon/HelperViews/CurrencyInputView.swift b/TalerCommon/HelperViews/CurrencyInputView.swift index c3c5697b..485eb622 100644 --- a/TalerCommon/HelperViews/CurrencyInputView.swift +++ b/TalerCommon/HelperViews/CurrencyInputView.swift @@ -129,6 +129,13 @@ struct CurrencyInputView: View { availableString(available?.readableDescription ?? String(localized: "unknown")) } + /// Why the amount cannot be sent. Deliberately the same string the + /// payment sheet uses for `wallet-balance-available-insufficient`. + var insufficientHint: String { + String(localized: "payment_balance_insufficient_max", + defaultValue: "Balance insufficient! You don't have enough \(amount.currencyStr).") + } + func heading() -> (String, String)? { if let title { return (title, a11yTitle) @@ -166,6 +173,20 @@ struct CurrencyInputView: View { .accessibilityLabel(heading.1) .padding(.bottom, -6) } + if insufficient { + // Turning the heading red was the whole message: no words for + // a sighted user, and nothing at all for VoiceOver, which + // reads the unchanged `heading.1`. The payment sheet already + // says this in words (PaymentScan.swift:207-211 via + // InsufficientBalanceHint.localizedCause), so reuse that + // string rather than invent a second one -- it is already + // translated. + Text(insufficientHint) + .padding(.horizontal, 4) + .frame(maxWidth: .infinity, alignment: title != nil ? .leading : .trailing) + .talerFont(.subheadline) + .foregroundColor(WalletColors().errorColor) + } currencyField .frame(maxWidth: .infinity, alignment: .trailing) .foregroundColor(WalletColors().fieldForeground) // text color diff --git a/TalerWallet1/Views/HelperViews/AmountInputV.swift b/TalerWallet1/Views/HelperViews/AmountInputV.swift index 87482845..268c9c7f 100644 --- a/TalerWallet1/Views/HelperViews/AmountInputV.swift +++ b/TalerWallet1/Views/HelperViews/AmountInputV.swift @@ -106,7 +106,15 @@ struct AmountInputV: View { let currency = amountToTransfer.currencyStr let coinData = CoinData(coins: numCoins, fee: feeAmount) let flags = checkAvailable(coinData) - let hint = String(localized: "enabled when amount is non-zero", comment: "a11y") + // One hint for three different reasons was wrong twice over: a + // VoiceOver user with too high an amount was told the button needs a + // non-zero one, and the real reason -- not enough money, or too many + // coins -- was never spoken at all. + let hint = flags.insufficient + ? String(localized: "enabled when the amount fits the available balance", comment: "a11y") + : coinData.tooMany + ? String(localized: "enabled when the amount is small enough for a single transfer", comment: "a11y") + : String(localized: "enabled when amount is non-zero", comment: "a11y") ScrollView { VStack(alignment: .trailing) { CurrencyInputView(scope: scope, amount: $amountToTransfer,