View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0011988 | Taler | wallet (iOS App) | public | 2026-11-09 23:42 | 2026-11-09 23:42 |
| Reporter | bot-cg [agent] | Assigned To | Resolution deadline | ||
| Implementer | Reviewer | ||||
| Release signed by | Deployed by | ||||
| Verifier | Communicator | CM_7 | |||
| Data protection authority notification required | No | ||||
| CSIRT notification required | No | ||||
| Estimated effort (hours) | Actual effort (hours) | 0 | |||
| Fast-track | No | ||||
| Work package | none | ||||
| Priority | normal | Severity | minor | Reproducibility | have not tried |
| Status | new | Resolution | open | ||
| Summary | 0011988: P2P transfer screen titles itself "Ready" while the card below also shows "Ready" -- the list's entry point shows "Send Money" and does not duplicate | ||||
| Description | After starting a peer-to-peer transfer the screen's title is "Ready", and the detail card below it shows "Ready" again on the right. Entering the same transaction later from the transactions list shows "Send Money" instead, which says something the state line does not -- so the duplicate is specific to the screen you land on first. Captured by the fuzzing harness (`iq3-e00000`, screens 35 and 36), iPhone 17 (402x874 pt), iOS 27.2: staticText "Ready" [16, 64, 100, 41] <- the navigation title staticText "7 November 2026 at 12:00" staticText "Ready" [307, 154, 79, 38] <- the transaction's state Screenshot attached (`11988-ready-twice.png`), cropped to the two. **The two sources.** * `P2PReadyV.swift:89` hardcodes the title: `let navTitle = String(localized: "Ready")`, passed into `TransactionSummaryList(navTitle:)`. * The card's state line is `txStateLcl` in `ThreeAmounts` (ThreeAmountsSection.swift:49-50), and for a *pending* peer transfer the minor state is `ready`, whose localization is "Ready" (Transaction.swift:79, `MinorState.ready`). **When it shows.** The state line prints the minor state only when `developerMode && pending`, and `developerMode` defaults to **true in a DEBUG build** (ThreeAmountsSection.swift:25-29). In a release build the line reads "Pending" and the two do not collide. So this is what a tester or a nightly user sees, which is consistent with the report against 1.6.18. **Why the other entry point is better.** `TransactionsListView.swift:213` passes `navTitle: nil`, and `TransactionSummaryList.navTitleStr` then derives the title from the transaction -- `talerTX.localizedType`, i.e. "Send Money" or "Request Money". That title is not available anywhere else on the screen, whereas "Ready" is already on it. | ||||
| Steps To Reproduce | 1. Actions -> Send (or Request), enter an amount, continue until the transfer is created. 2. Look at the title and at the right-hand side of the detail card. Observed: "Ready" in both places. Expected: one of them. The title should say what the transaction is -- the list's entry point already does. 3. Go back, open the same transaction from the transactions list. The title now reads "Send Money" and nothing is duplicated. On a release build the state line reads "Pending" instead, so reproduce on a debug/nightly build or with developer mode on. | ||||
| Additional Information | Patch attached: `ready-twice.diff`. `P2PReadyV` passes `navTitle: nil`, which is exactly what the transactions list passes, so both entry points title the screen from the transaction. One line plus the reasoning. An alternative I did not take: suppress the state line when it equals the title. That keeps a title that says less, and it would paper over the collision rather than remove it -- "Ready" as a title tells the user nothing they cannot see from the state line itself. **NOT YET COMPILED**: the one machine that builds this app is in the middle of an unattended two-hour measurement and a build would perturb it. I will confirm in a follow-up note. **Why the harness's own screen survey missed this**, which is the part worth fixing beyond the bug: the survey (11986) *did* capture this screen and *did* see both labels, and threw the pair away. Its rule was "a duplicate must appear in at least two distinct episodes", written against analyzers that believed a single animation frame -- and this pair occurs in one episode, on two consecutive screens. Rarely-visited screens are exactly where defects survive, so the threshold was filtering out the evidence it was most needed for. It now counts distinct screens as well as episodes. That is the second miss a user has had to report today; the first was a chooser drawn as segments, which the survey could not see at all (11987). | ||||
| Tags | No tags attached. | ||||
| Attached Files | ready-twice.diff (2,208 bytes)
diff --git a/TalerWallet1/Views/Actions/Peer2peer/P2PReadyV.swift b/TalerWallet1/Views/Actions/Peer2peer/P2PReadyV.swift
index 98ec9861..5f28b67a 100755
--- a/TalerWallet1/Views/Actions/Peer2peer/P2PReadyV.swift
+++ b/TalerWallet1/Views/Actions/Peer2peer/P2PReadyV.swift
@@ -86,14 +86,32 @@ struct P2PReadyV: View {
let _ = Self._printChanges()
let _ = symLog.vlog() // just to get the # to compare it with .onAppear & onDisappear
#endif
- let navTitle = String(localized: "Ready")
+ // No hardcoded title: the summary derives one from the
+ // transaction itself (`navTitleStr` -> `talerTX.localizedType`),
+ // which is what the transactions list already passes `nil` to get.
+ //
+ // Hardcoding "Ready" said the same thing twice. The detail card
+ // shows the transaction's state on its right, and for a pending
+ // peer transfer that state IS `ready` -- `MinorState.ready`,
+ // "Ready" (Transaction.swift:79) -- so the screen read
+ //
+ // staticText 'Ready' [16, 64, 100, 41] the title
+ // staticText 'Ready' [307, 154, 79, 38] the state
+ //
+ // captured in `iq3-e00000` seq 35 and 36. The state line shows the
+ // minor state when `developerMode && pending`, and `developerMode`
+ // defaults to true in a DEBUG build
+ // (ThreeAmountsSection.swift:25-29), so that is what a tester sees.
+ //
+ // Entering the same transaction from the list instead shows
+ // "Send Money", which says something the state line does not.
ZStack {
if let transactionId {
TransactionSummaryList(stack: stack.push(),
// scope: scope,
transactionId: transactionId,
talerTX: $talerTX,
- navTitle: navTitle,
+ navTitle: nil,
hasDone: true, // conclude p2p
showDone: .prominent,
url: nil,
| ||||