Repository navigation
fix: improve usdt deposit accessibility - #1002
Conversation
[Medium impact] The changes affect USDT deposit readability and shared scanner interactions. The PR appears safe to merge, with a non-blocking gap in the new sizing test. Findings
SummaryThis PR stacks deposit history fields and detail summaries at accessibility text sizes. It also lets drags over the camera preview reach the recipient scroll view.
Reviews (1) · Last reviewed commit: "fix: improve usdt deposit accessibility" · Reviewed by Greptile |
talosmachina
left a comment
There was a problem hiding this comment.
No findings. Stacks the USDT deposit history row and the deposit detail Status/Receiving Network pair at accessibility text sizes, and lets drags on the scanner preview reach the enclosing scroll view. Reviewed d232d6a, full tier, reasoned from the code and CI (iOS does not build on this reviewer's Linux host).
What I checked, and 4 candidates I ruled out
Read in full: Scanner.swift, ActivityRow.swift, UsdtDepositHistoryView.swift, ComponentSizingTests.swift, and the six journey hunks
Call sites traced: ActivityRowContent (lightning, onchain and USDT activity rows keep the default stacked = false, so their layout is unchanged); Scanner (all six callers: scanner screen and sheet, send options, USDT send, seed QR, probing tool)
CI: Run Tests still pending at review time; Greptile passed
Ruled out
- Disabling hit testing on the camera drops a camera gesture:
QRCodeScannerViewControllerhas no tap-to-focus, pinch or touch handling, and none of the sixScannercallers attaches a gesture to it, so.allowsHitTesting(false)removes nothing. The photo picker and torch sit inScannerCornerButtons, which stays hit-testable. .contentShape(Rectangle())on the scanner swallowing the scroll drag: no gesture is attached at that level, so the shape only defines the hit area. It does not compete with the scroll view's pan.- Stacked row breaking the other activity rows:
stackedis opt-in, and onlyUsdtDepositRowpasses it. - Amount truncation at AX sizes:
lineLimit(nil)together with.fixedSize(horizontal: false, vertical: true)lets the amount wrap.minimumScaleFactor(0.7)only kicks in when the text cannot grow.
The test's mismatch between measured text and rendered text is already raised in Greptile's inline thread, so it is not repeated here. The physical-camera drag is only covered by the PR's manual test: in the simulator the preview is Color.black, not ScannerCamera.
Merge confidence: 4/5. No findings, but CI was still running and no test covers the device camera path (the simulator renders a placeholder there).
There was a problem hiding this comment.
Verdict:
Findings:
-
LOW
Bitkit/Views/Wallets/Activity/ActivityRow.swift:104: at accessibility sizes the stacked deposit cards shrink to their content width. Dropping theSpacerremoves the only thing that stretched the row, so each card is as wide as its longest line and left-aligned, with ragged right edges between rows and a narrower tap target. The new sizing test checks heights only, so it does not catch this.
QA for b3e6025:
Tested on an iPhone 17 Pro simulator (iOS 26.5) with four deposits: Ethereum and BNB Smart Chain needing attention, Polygon confirmed, Tron pending.
Test 1: deposit history at the largest text size ✅ Every row shows its full network, status and amount.
At AX5 all four rows stack, including "BNB Smart Chain", "Needs attention" and "1.234,56 USDT", with no ellipsis.
t1.2x.mp4
Test 2: deposit summary at the largest text size ✅ Status and Receiving Network stack in one column.
"RECEIVING NETWORK" wraps between words and "Arbitrum One" stays whole.
t2.2x.mp4
Test 3: default text size ✅ The two-column summary and the compact full-width rows return.
t3.2x.mp4
Test 4: drag on the scanner preview ✅ A drag that starts inside the preview scrolls to Paste, Enter Manually and the network warning.
At AX5 the flashlight button toggles and the photo picker opens. The simulator renders a black placeholder in place of the camera, and the base build 73f2bf4 scrolls from the same drag (second video), so this shows no regression but not the fix.
t4.2x.mp4
t4-base.2x.mp4
Test 5: live camera on a physical iPhone ⏭️ Not run: needs a physical iPhone with a camera.
The PR's manual test (scroll from the live preview, QR image import, torch) is still open.
Not driven: the steps added to contact-request-or-pay.xml, request-summary.xml, usdt-receive-amount-and-units.xml and usdt-send-review-and-details.xml cover the pair PR; this PR changes no iOS code on those paths.
Outside this PR: UsdtActivityRow and the UsdtActivityDetail summary keep one-line rows and the two-column grid, so the USDT activity list still truncates "Received" to "Rec…" at AX5.
Pair PR synonymdev/bitkit-android#1564 shares the journey updates and marks the deposit-history and scanner steps as iOS-only, so there is no Android layout change to match.
Reviewed in full, 73f2bf4 to b3e6025, 11 files. No device case drove the ScannerCamera branch at Bitkit/Components/Scanner.swift:250.
jvsena42
left a comment
There was a problem hiding this comment.
Code scan: no HIGH/MEDIUM. One LOW (journey preconditions) is inline.
Checked and clean:
Scanner.swiftonly changes hit-testing on the placeholder and the ZStack;onScan, parsing and haptics are untouched.- The deposit row keeps the masked value in both layouts, and stacking removes the line limit only at accessibility sizes.
Perf: not relevant (AnyLayout switch on dynamicTypeSize only).
The six journey file names and the added action prose match the twin synonymdev/bitkit-android#1564.
Device gate (partial): not run yet. Pending: the six changed journeys, a perf check and Check 5. The device result follows in a second review.
|
Applied the matching narrow-card fix from Android #1564 in aff5b7b. Request contacts and amounts remain beside each other when they fit; longer summaries stack so names and localized receipt words remain complete. Checked synthetic USDT/USD/BTC cards at 320pt with normal, XXX Large and accessibility text, plus compact short-status cards. All 2,622 unit tests pass, SwiftFormat is clean across the PR’s Swift diff, and translations report zero errors with the same three keys inherited from #973. The paired journey now specifies the real padded width. All five PR commits are signed and verified locally and on GitHub. |
jvsena42
left a comment
There was a problem hiding this comment.
Delta since my last review, edd752a: docs only. My journey thread is fixed. The BTC receipt now rounds to the payer's Payment value, and the 375-pt note is in place.
One LOW is inline (long note stacks the card header), with a failing test.
Device gate (partial): not run yet. Pending: request-summary.xml last action, at 375 pt with enlarged and default text.
There was a problem hiding this comment.
Verdict:
Findings: None. I confirmed the stacked deposit-card width fix at edd752a.
QA for edd752a:
Tested on iPhone SE (3rd generation) simulators, iOS 26.5, 375 pt, dark mode. Recordings play at 2×.
Test 1: deposit history width ✅ Polygon, Tron and BNB Smart Chain cards fill the history width at AX1 and AX5; default text restores compact rows.
Network, status and amount remain readable, including the short Polygon row that previously left unused space on its right.
case1.2x.mp4
Test 2: verified request history ✅ Genuine USD and BTC requests paid in USDT retain complete Polish statuses and exact receipts at AX1 and default text.
The USD request and receipt are both 1.23. The BTC request's receipt is 0,82063 USDT, which rounds to the payer's 0.82 Payment value; its 0.68 fee makes the activity total 1.50. The recording shows both wallets side by side, requester on the left. The short pending card stays horizontal at default text; verified receipts stack when needed.
case2.2x.mp4
Test 3: contact loading and retry ✅ Selection remains on the resolving contact; an endpointless contact shows an error and allows a successful retry with the original contact.
Tapping Empty while Maria is loading leaves Maria selected. After cancelling and reopening Send, Empty shows “Unable To Pay Contact.” Selecting Maria then opens its USDT amount screen. Cancelled without payment.
case4.2x.mp4
Test 4: receive 3.50 precision ✅ The decoded QR and copied/shared URI retain `uint256=3500000`, and sharing identifies Arbitrum One.
Checked the QR with a decoder and compared the copied URI and share-sheet Copy payload through the clipboard. Show Details copies the same wallet address without URI parameters.
case5.2x.mp4
Test 5: live camera and torch ⏭️ Unrun: the available physical iPhone is personal; simulators cannot verify live capture or a physical torch.
A dedicated test iPhone is needed to verify dragging from the live preview, QR photo import and the torch together. The prior simulator result does not prove the live-camera branch.
I carried forward the unchanged deposit-detail AX5 and simulator-preview checks from the prior review.
Coverage: delta b3e6025..edd752a, all eight changed files and their reached code, plus the prior width finding. Device coverage targets the changed journey actions; the Android-only navigation-inset action and documentation prerequisites were reviewed in code.
Twin: synonymdev/bitkit-android#1564 fix: improve usdt payment feedback and layout matches the request-history assertions, with the documented iOS 375 pt / Android 320 dp difference.
Reviewed by gpt-6.1-sol-high via gh-pr-review-loop skill
Commands: @ovi-reviewer review · test · retest
|
Device gate (partial):
Observation outside this diff: the Subscriptions tab identifiers are localized ( |
|
Device gate addendum (
|
jvsena42
left a comment
There was a problem hiding this comment.
Approving at edd752a. My journey thread is resolved. One LOW stays open: a long note stacks the pending card header. Fix it here or in a follow-up, your choice, and reply on the thread with which.
Device gate: edd752a — journeys: payment-requests/request-summary.xml last action and payment-requests/contact-request-or-pay.xml pass on the iPhone 17 simulator, with synonymdev/bitkit-android#1564 on Android as the counterparty; perf: not relevant; l10n: Polish checked at accessibility-large.
- Receipts: "3.00 USDT" for the $3.00 request, and "2.4603 USDT" for the ₿3,000 request, which rounds to the payer's Payment value of 2.46.
- Layout: at accessibility-large in Polish everything stays complete and wraps below the contact. At default size in English it sits beside the contact.
- Contact pay: the Pay spinner shows with Request disabled, and the tapped row shows a spinner while the other row is ignored. The endpoint-less contact gives
23:01:04.335 Failed to resolve Paykit contact payment … reason=not_found, then the "Unable To Pay Contact" toast, and both rows are enabled again. Selecting Gate then opens the amount screen (23:05:38.589 Opened private Paykit payment). - Step 7 timing: the 3-second target was missed (4–6 s from tap to SendAmount). That time is Paykit resolution against staging, which this PR doesn't touch, and Android shows the same.
Observation outside this diff, for a possible follow-up: within one Send sheet, going Back from a contact's amount screen and selecting any contact again resolves (Opened private Paykit payment …) but never navigates. It reproduced 4 times. Closing and reopening Send clears it. SendContactSelectView.openContactPayment returns early on guard app.claimContactPaymentContext(...) with no log, which fits a context still claimed after Back.
CI at edd752a: green apart from e2e-tests-local, which was still running; check it before merge.
|
The long-note layout is already deferred to #1030 (3.1.0), now clarified on its thread. I also verified the Back/reselect context gap in current master and tracked it separately in #1034 with the ownership and regression-test requirements; it is outside this accessibility diff. Android does not use the same claim guard. Both follow-ups are linked under Out of Scope. |
|
Merged, as it was approved and green. |
Fixes #983
Targets
master, including the merged recipient-screen and shared accessibility fixes from #973.Related Android follow-up: synonymdev/bitkit-android#1564
Description
Out of Scope
Contact Back/reselect navigation: Contact payment cannot be selected again after returning from Amount #1034 (review observation); this predates the accessibility diff.
Long-note header layout at default text size: Keep long request notes from stacking the default-size header #1030 (review thread).
The stale paid-request report ([Bug]: Stale payment request remains briefly actionable after initial USDT subscription payment #982) and broader restore/profile report (paykit private_payments policy error stalls restore and profile re-creation #984); their causes are not established by these layout changes.
Provider operations, transfers and new network-warning designs.
Design
Adapts the existing bridge details using the accessibility layout pattern already in #973. Request cards reuse the existing payment request layout. The latest handoff page reference for this fix is not confirmed; no normal-size redesign.
Preview
See #983 for the affected layouts. Simulator screenshots of the corrected recipient scroll were captured locally; no screenshot attachment is available yet.
QA Notes
Journeys
usdt-bridge-details.xml— full history fields and a single-column detail summary at the largest accessibility text size, restoring the compact layout at normal text.usdt-payment-links-and-scans.xml— drag over the camera preview to reach recipient controls and the network warning, keeping gallery and flashlight usable.contact-request-or-pay.xml— shared contact-resolution loading/retry coverage; iOS already provides this feedback.request-summary.xml— shared long-status and exact-amount readability coverage.usdt-receive-amount-and-units.xml— shared3.50input,3.5share text and unchanged QR atomic amount.usdt-send-review-and-details.xml— shared Android navigation-inset check, explicitly scoped to Android.The shared journey prerequisites now explicitly include the linked payment contacts, one-time/subscription requests and completed USDT receipts. The history check compares USD receipts with the request amount and BTC-denominated receipts with the rounded Payment value in the payer’s activity detail, excluding fees. It uses a supported 375-point device on iOS (320 dp on Android); the retry check uses a contact without payment endpoints. XML and cross-platform changed-action parity were checked. This documentation update does not claim a new run of the full funded journeys.
Manual Tests
Automated Checks
ComponentSizingTests.swift— a deposit with a long network name and six-decimal amount grows vertically at accessibility sizes; existing button and title sizing remains covered.Validation: simulator build and all 2,622 unit tests passed, including the four sizing tests. Synthetic request-card captures at 320pt with normal, XXX Large and accessibility text were checked for USDT, USD and BTC denominations. SwiftFormat reports no changed-file formatting violations. Translation validation has zero errors and the same three untranslated keys inherited from #973; no strings changed here. Full deposit-history fixture and physical-camera journeys remain for reviewer QA.