Skip to content

fix: aggregate token tab auto-enable, network sheet sizing, uncreated-address value, cold-start home images, custom token keyboard dismiss, tooltip close(OK-61863, OK-61860, OK-61879, OK-61505, OK-61527, OK-61417, OK-61524) - #13218

Open
weatherstar wants to merge 9 commits into
xfrom
fix/wallet-issues

Conversation

@weatherstar

@weatherstar weatherstar commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

OK-61863 OK-61860 OK-61879 OK-61505 OK-61527 OK-61417 OK-61524


Summary

  • Aggregate token details: jumping to a member tab now enables only the landed network and toasts once; the "Select network" and "Contract address" sheets size to their content instead of a fixed 92% snap; the aggregate network selector no longer shows an asset value next to "Create address" rows.
  • Home cold start: wallet tab support and the banner image no longer jitter or flash a skeleton on the first frame (swrKey snapshot + image prewarm).
  • Add custom token page: a blank tap or drag dismisses the keyboard.
  • Tooltip (web/desktop): closes on trigger press and before a modal is pushed, so it never lingers above a new modal.
  • Tests: lock background RPC error rehydration against a getter-only constructorName (regression guard for the "loading forever" RPC hang).

Intent & Context

QA reported a batch of App-6.6.0 wallet issues, most of them in the aggregated token flows on Android:

  • OK-61863: with only Arbitrum enabled in All Networks, tapping the 4th network in the USDC overview enabled every network in between and stacked 4 "network enabled" toasts; returning to Overview toasted again.
  • OK-61860: the "select more networks" sheet on Android had a large blank band under the last row and the sheet moved oddly when scrolling.
  • OK-61879: in the aggregate network selector (Receive / Buy), networks without a created address showed "$0.00" next to the "Create" button.
  • OK-61505: home tabs jittered and the banner showed a skeleton on cold start.
  • OK-61527: the keyboard could not be dismissed by tapping blank space on the custom token page.
  • Tooltip: a hover tooltip stayed open above a freshly pushed modal (desktop home "Copy address" → WalletAddress modal).
  • OK-61417: the main-thread RPC error rehydration hang was fixed on x earlier; this adds the missing test lock.

Root Cause

  • OK-61863 (two causes). (1) Android's ViewPager2 dispatches onPageSelected(target) at the start of a programmatic smooth scroll. The react-native-collapsible-tab-view patch treated that as arrival and cleared its programmaticPageTarget guard, so the following absolute onPageScroll positions (0→4) propagated every rounded transit index through onIndexChange, and the page auto-enabled each transit network. iOS is unaffected: its offset is interpolated by |destination − current| and onPageSelected fires at the end. (2) The library's index-propagation reaction has fixed deps, so the onIndexChange closure is frozen at first render; handleTabIndexChange kept reading the pre-enable allNetworksState snapshot and toasted again for networks it had already enabled.
  • OK-61860. Both aggregate popovers passed sheetProps={{ snapPoints: [92], snapPointsMode: 'percent' }}, so the native sheet was always 92% tall regardless of content. Switching to the default fit mode alone is not enough: Tamagui caps the fit-mode Sheet.ScrollView at the full screen height, so header + list overflowed the screen (header under the status bar, last rows clipped) — reproduced on the emulator with USDT's ~20 members.
  • OK-61879. AggregateTokenListItem rendered the balance/value column unconditionally; rows for networks with no derived address have no home sub-token entry and Currency maps undefined to '0', hence "$0.00". The old account lookup returned a bare string | undefined, so "pending" and "no address" were indistinguishable.
  • OK-61505. Tab support resolved to an all-false init result with no snapshot on cold start, and the banner image source was never prewarmed, so SDWebImage's async disk load showed a skeleton.
  • OK-61527. The project has no global tap-outside keyboard dismiss; the page needed the Receive-page pattern (Page scrollEnabled + keyboardDismissMode="on-drag" / keyboardShouldPersistTaps="handled").
  • Tooltip. Tamagui tooltips only close on mouseleave; the pointer does not move when a modal appears and the tooltip portal always paints above modals.

Design Decisions

  • Patch fix at the source (OK-61863). handlePageSelected now keeps the programmatic target alive until the pager visually reaches the page (Math.round(indexDecimal) === selectedIndex), while still syncing index immediately so the tab highlight stays instant. The guard is released by the reaction at visual arrival, by a non-settling scroll state, or by the iOS fallback timer (which now also syncs indexDecimal). Landing on a different page (user interrupted the scroll) still releases the target, so swipes are never blocked.
  • Live state, not the closure (OK-61863). enableNetworkInAllNetworksOnce reads getAllNetworksState() from the background at decision time and dedupes in-flight networks; handleTabIndexChange reads aggregateTabs through a ref. Any native Tabs.Container onIndexChange consumer must not rely on closure freshness.
  • Content-sized sheets with a bounded frame (OK-61860). Drop the percent override and, in Popover (native and web files are separate), measure the sheet header via onLayout and pass maxHeight = floor(viewportHeight × 0.92) − headerHeight − (bottomInset || 20) to Sheet.ScrollView when the sheet is in fit mode. Short lists stay compact, long lists cap at the previous 92% footprint and scroll. Sheets that explicitly pass percent/constant snap points are untouched.
  • Settled tri-state lookup (OK-61879). The account lookup settles to { accountId } so the value column is hidden only once the lookup settles without an account; while pending it stays put, so rows that do have an address never blink their balance in after the first frame (Android modals open without animation, so first-frame round trips are visible). Rows with an address on a disabled network still show "$0.00" (product accepted).
  • Tooltip latch on pointerdown. Mouse/pen pointerdown on the trigger closes the tooltip and keeps it closed until the pointer leaves; touch is exempt because a tap is the only way to reveal a tooltip there. pushModalPage calls closeAllTooltips() via a small registry.

Changes Detail

  • patches/react-native-collapsible-tab-view+8.0.1.patch: programmatic-target lifecycle in handlePageSelected / handlePageScrollStateChanged / iOS fallback; the index reaction releases the guard at visual arrival even when index was already synced.
  • packages/kit/src/views/AssetDetails/pages/TokenDetails/index.tsx: tab-change auto-enable uses the new helper + refs; contract-address popover drops the 92% snap.
  • packages/kit/src/views/AssetDetails/pages/TokenDetails/tokenDetailsNetworkAutoEnable.ts (+ test): live-state, single-flight enable helper.
  • packages/kit/src/views/AssetDetails/pages/TokenDetails/TokenDetailsTabToolbar.tsx: "Select network" popover drops the 92% snap.
  • packages/components/src/actions/Popover/index.tsx, index.native.tsx: header-measured Sheet.ScrollView cap for fit-mode sheets.
  • packages/kit/src/views/AssetSelector/pages/AggregateTokenSelector.tsx (+ test): settled account lookup; value column hidden on networks without an address.
  • packages/kit/src/views/Home/hooks/useHomeWalletTabSupport.ts, packages/kit/src/utils/coldStartImagePreload.ts, WalletBanner.tsx, homeWalletTabSupportUtils.ts, swrCacheUtils.ts (+ tests): cold-start snapshot and banner prewarm.
  • packages/kit/src/views/AssetList/pages/AddCustomTokenModal.tsx (+ test): scrollable page with keyboard dismiss on drag / handled taps.
  • packages/components/src/actions/Tooltip/*, packages/kit/src/hooks/useAppNavigation.ts (+ tests): pointerdown latch, tooltip registry, close-all on modal push.
  • packages/kit-bg/src/.../setupBackgroundThreadRPCHandler.test.ts, setupMainThreadBackgroundRunner.test.ts: regression tests for OK-61417.

Risk Assessment

  • Risk Level: Medium
  • Affected Platforms: Mobile (Android, iOS), Desktop, Web, Extension
  • Risk Areas:
    • The collapsible-tab-view patch affects every native Tabs.Container consumer (market tabs, home tabs, token details). Programmatic jumps now propagate one index change at the early Android onPageSelected (highlight still instant) instead of one per transit page; iOS behavior is unchanged except the fallback timer also syncs indexDecimal.
    • The Popover cap applies to every fit-mode sheet on native and mobile web; it only bites when content exceeds ~80% of the screen, which previously overflowed anyway.
    • The tooltip pointerdown latch applies to all web/desktop tooltips.

Test plan

  • Unit: AggregateTokenSelector.test.tsx (3), tokenDetailsNetworkAutoEnable.test.ts (5), tooltip registry / open-state / navigation hook tests, AddCustomTokenModal.test.tsx, useHomeWalletTabSupport + coldStartImagePreload tests, OK-61417 RPC rehydration tests.
  • yarn agent:check --profile commit green on every commit.
  • Android emulator (dev shell), OK-61863: baseline reproduced 4 stacked toasts when tapping the 4th network; fixed build shows 1 toast, transit networks (Tron / Ethereum / Solana) stay disabled, no toast on returning to Overview or re-entering the enabled tab.
  • Android emulator, OK-61860: USDT "Select network" sheet stays below the page header, scrolls to the last row, no blank band; patch verified to apply cleanly to pristine react-native-collapsible-tab-view@8.0.1.
  • Android device, OK-61860: open the aggregate token "select network" sheet for a token with few members (the reporter's case) and confirm the sheet wraps its content with no blank band.
  • Android + iOS device, OK-61879: only Arbitrum enabled → new account → USDC → Receive; SUI / Aptos / Near rows show only the "+" icon, no "$0.00".
  • iOS device, OK-61863: jump from Overview to the 4th member tab and back; one toast, no transit networks enabled.
  • iOS + Android device, OK-61505 / OK-61527 (already device-verified by the authoring sessions, re-check on the formal build).
  • Desktop, tooltip: hover "Copy address" on home, press it; the tooltip closes and the WalletAddress modal opens without a lingering tooltip.
  • Smoke the market tabs on Android (programmatic tab sync) since the collapsible-tab-view patch changed.

A hover tooltip stayed open above a freshly pushed modal (desktop home
"Copy address" -> WalletAddress modal) because Tamagui tooltips only
close on mouseleave, the pointer does not move when a modal appears, and
the tooltip portal always paints above modals.

- Tooltip (web): a mouse/pen pointerdown on the trigger closes the
  tooltip and keeps it closed until the pointer leaves the trigger.
  Touch is exempt because a tap is the only way to reveal a tooltip
  there. Uses pointerdown instead of onPressIn, which fires for both
  mousedown and touchstart.
- tooltipRegistry: track open tooltips and expose closeAllTooltips();
  useAppNavigation.pushModalPage calls it so shortcut- or event-driven
  modals never open under a lingering tooltip.
- Unit tests for the registry, the open-state hook, and the navigation
  hook; desktop verified over CDP.
@weatherstar
weatherstar enabled auto-merge (squash) September 7, 2026 11:35
@weatherstar weatherstar changed the title fix: aggregate token tab auto-enable, network sheet sizing, uncreated-address value, cold-start home images, custom token keyboard dismiss, tooltip close(OK-61863, OK-61860, OK-61879, OK-61505, OK-61527, OK-61417) fix: aggregate token tab auto-enable, network sheet sizing, uncreated-address value, cold-start home images, custom token keyboard dismiss, tooltip close(OK-61863, OK-61860, OK-61879, OK-61505, OK-61527, OK-61417, OK-61524) Sep 7, 2026
@sidmorizon

Copy link
Copy Markdown
Contributor

@codex review

@sidmorizon

Copy link
Copy Markdown
Contributor

@codex security review

@sidmorizon

Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 7, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-07T11:52:51.702382Z dfa42d5 Manual request
🔒 Security Review Completed 2026-09-07T11:54:16.114984Z dfa42d5 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

Reviewed commit: dfa42d5511

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +288 to +294
const sheetScrollViewMaxHeight = isFitSheet
? Math.max(
0,
Math.floor(viewportHeight * FIT_SHEET_MAX_HEIGHT_RATIO) -
sheetHeaderHeight -
(bottom || SHEET_BOTTOM_MARGIN),
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keyboard-open fit sheets overflow

Severity: non-severe

When a tall fit sheet opens the keyboard, sheetScrollViewMaxHeight reserves no keyboard space. The frame adds keyboardHeight separately, while the token selector auto-focuses its search field. Its header or bottom rows can leave the viewport.

@chatgpt-codex-connector

Copy link
Copy Markdown

Security review completed. No security issues were found in this pull request.

Reviewed commit: dfa42d5511

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants