View Issue Details

IDProjectCategoryView StatusLast Update
0011963Talerwallet (iOS App)public2026-11-07 21:27
Reporterbot-cg [agent] Assigned ToResolution deadline
ImplementerReviewer 
Release signed byDeployed by 
VerifierCommunicatorCM_7  
Data protection authority notification requiredNo  
CSIRT notification requiredNo  
Estimated effort (hours)Actual effort (hours)0 
Fast-trackNo
Work packagenone
PrioritynormalSeverityminorReproducibilityhave not tried
Status newResolutionopen 
Summary0011963: Add bank account: the Add button stays disabled when only the IBAN is filled in, with no hint why, and a failed save is silent
DescriptionAdding a bank account can get stuck with no feedback at all. Three things in
TalerWallet1/Views/Settings/Bank/BankEditView.swift combine:

**1. The IBAN field does not clear `unchanged`, so Add stays disabled.**

Line 73: `.disabled(disabled || notValid || unchanged)`.

`unchanged` starts `true` (line 42) and is cleared in exactly three places --
`onChange(of: accountLabel)` (lines 195-199), `onChange(of: accountHolder)`
(lines 217-221) and `onChange(of: xTaler)` (lines 265-271) -- each guarded by
`if userTyped`, and `userTyped` is set only by a focus change (lines 296-303).
The IBAN field's own `onChange` (lines 253-260) only starts the
`model.validateIban` task; it never touches `unchanged`.

So a user who fills in just the IBAN -- the one field the button's own
validation (`notValid = iban.isEmpty || !ibanValid`) is about -- sees Add stay
greyed out permanently, with nothing on screen saying what is missing. The
button has no accessibility hint and there is no inline validation text.

**2. When the save does run and fails, nothing is shown.**

`updateAccount()` (lines 104-...) returns `false` without any user-visible
effect unless *both* `accountHolder` and `accountLabel` are non-empty
(line 106). On the failure paths it sets `showAlert = true` (e.g. line 127,
after a payto URI that cannot be assembled) -- but `showAlert` is declared at
line 32 and **bound to no `.alert` modifier anywhere in the file**. The flag
is written and never read. `symLog.log("error addBankAccount")` (line 136) is
the only trace, which the user cannot see.

**3. A dead accessibility label.**

Minor, same screen: lines 65-67 compute `a11yStr` as "Add bank account" /
"Update bank account", but `DoneButton(titleStr:accessibilityLabelStr:)` is
called with `titleStr` for both arguments (line 70), so the computed label is
never used and the button is announced as just "Add".

Found while writing a deterministic UI test for this flow: the test filled the
IBAN, waited for the button to become enabled, and timed out. The field order
turns out to be load-bearing in a way nothing on the screen indicates.
Steps To Reproduce1. Settings -> Bank Accounts -> + (add).
2. Leave "Label" and "Account holder" empty and type a valid IBAN into the
   IBAN field, e.g. CH9300762011623852957.

Observed: "Add" stays disabled indefinitely, with no indication of what is
missing. Filling in "Label" (or "Account holder") afterwards enables it.

3. For the silent-failure part: reach any `updateAccount()` failure path --
   e.g. an account holder string that makes `URLComponents.string` nil, or a
   wallet-core `addBankAccount` rejection.

Observed: the view stays as it is, no alert, no error text. `showAlert` is
set but no `.alert` is attached to it.

Expected: either the button is enabled once the form is actually valid (all
three fields participating in the enabled state), or the screen says which
field is still required -- and a failed save reports something.
Additional InformationSuggested fix:

* Let the IBAN/xTaler field participate in `unchanged` like the other two
  (clear it in the IBAN `onChange` as well), or -- better -- drop `unchanged`
  from the `.disabled` expression for a *new* account, where "unchanged" is
  not a meaningful state, and compute validity from the fields the save
  actually requires: label, holder and the payto target.
* Add an `.accessibilityHint` (and ideally visible helper text) naming the
  missing field while the button is disabled. The same codebase does this
  elsewhere -- e.g. the P2P subject screen's "enabled when subject and
  expiration are set".
* Bind `showAlert` to an `.alert`, or remove it and report the error some
  other way. As it stands the failure is invisible to the user and to a test.
* Pass `a11yStr` to `DoneButton`'s `accessibilityLabelStr` parameter, which
  is presumably what lines 65-67 intended.

Severity is a judgment call: nothing is lost or corrupted, but the screen can
reach a state where the user cannot proceed and is told nothing, which is how
it presented.
TagsNo tags attached.

Required notifications

Address or linkRemarkAdded byNotifiedActions

Activities

There are no notes attached to this issue.

Issue History

Date ModifiedUsernameFieldChange
2026-11-07 21:27bot-cgNew Issue