fix(mobile): stop clipping expanded tool groups - #10212
juliusmarminge merged 1 commit into
Conversation
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: unavailable · PR result: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a contained mobile UI bug fix that replaces the problematic masked group rendering with a clipped list and localized edge fades, while synchronizing expanded-group sizing with LegendList measurements. Its effects are limited to existing expanded tool groups and do not introduce new capabilities, schema changes, product-default changes, or static-analysis overrides. No code changes detected at You can add or adjust custom eligibility rules. Learn more. |
Opening a row's details inside a tool group left an unpainted band the size of the growth: the group's MaskedView hosts the list inside a SwiftUI mask whose native bounds kept the old height, so everything past it was clipped even though layout and accessibility frames were right. Draw the scroll-edge fades as screen-colored gradients over a plain clipped view instead, and read the group's content size from LegendList's layout so the outer row resizes in the same commit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
5e25d25 to
65b1b9c
Compare
When the PR selected for `early` does not apply at the reconciled upstream boundary, the command stopped with a single line that gave nothing to act on: ```console $ node scripts/upstream-queue.ts early 11784 --through upstream/main Selected pingdotgg#11784 cannot be applied at the upstream boundary. ``` That happens when the PR builds on upstream work the fork has not taken in yet, and the planner only looks for dependencies in the changes it replays after a successful apply. The command now reports which of the PR's files conflict at the boundary and which earlier pending upstream PRs and direct commits change those files, in upstream order. Text output lists the first 20 and says how many remain; `--json` includes every source with its SHA, PR, and title. A plan that succeeds prints as before. The intake runbook's `early` paragraph describes the report. ## Validation - A new test in `scripts/upstream-early.test.ts` checks which sources the report lists: pending sources after the boundary and before the blocked PR whose files overlap the conflicting paths, including direct commits and directory prefixes, and not recorded or later sources. - `scripts/upstream-early.test.ts` and `scripts/upstream-queue.test.ts` pass (21 tests); lint, formatting, and the scripts typecheck are clean. - Against fetched fork `main` (`495b7cfd5`) and upstream `main` (`b2b43bef7`), the same command now prints: ```console $ node scripts/upstream-queue.ts early 11784 --through upstream/main Fork 495b7cf; reconciled through d28077e pingdotgg#11784 does not apply at the reconciled boundary. 16 of its files conflict there: apps/mobile/src/features/threads/ThreadFeed.tsx apps/mobile/src/features/threads/thread-work-log.tsx apps/mobile/src/lib/threadActivity.ts apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts apps/server/src/orchestration/decider.ts apps/server/src/provider/Layers/ClaudeAdapter.test.ts apps/server/src/provider/Layers/ClaudeAdapter.ts apps/server/src/textGeneration/ThreadTitleContext.test.ts apps/server/src/textGeneration/ThreadTitleContext.ts apps/server/src/ws.ts apps/web/src/components/chat/MessagesTimeline.logic.ts apps/web/src/components/chat/MessagesTimeline.tsx apps/web/src/components/settings/SettingsPanels.tsx packages/client-runtime/src/state/environmentHttpAuth.test.ts packages/client-runtime/src/state/threadSnapshotHttp.ts packages/contracts/src/orchestration.ts Earlier pending upstream changes to those files: 110 PRs. Take them in first, or add their PRs to this plan. pingdotgg#9594 fix(connect): refresh HTTP credentials without reconnecting (pingdotgg#9594) pingdotgg#9894 fix(chat): show hours for long runs (pingdotgg#9894) pingdotgg#9933 fix(settings): share restart continuation across environments (pingdotgg#9933) pingdotgg#10092 fix(web): scale agent spawn rows with interface font (pingdotgg#10092) pingdotgg#9965 fix(web): keep the composer expanded until the thread can scroll (pingdotgg#9965) pingdotgg#9935 fix(web): align tool disclosure chevrons with expanded state (pingdotgg#9935) pingdotgg#10199 fix(mobile): size a chat image's frame before its bytes arrive (pingdotgg#10199) pingdotgg#10200 fix(web): size the chat image slot from server-reported dimensions (pingdotgg#10200) pingdotgg#10167 refactor(client-runtime): remove unused runtime exports and helpers (pingdotgg#10167) pingdotgg#10173 fix(mobile): restore live tool shimmer and add a Thinking row (pingdotgg#10173) pingdotgg#10210 fix(mobile): only make work rows expandable when the body adds something (pingdotgg#10210) pingdotgg#10211 fix(mobile): fold subagent lifecycle rows into one batch per spawn (pingdotgg#10211) pingdotgg#10212 fix(mobile): stop clipping expanded tool groups (pingdotgg#10212) pingdotgg#9875 feat: show provider usage limits with /usage-limits (pingdotgg#9875) pingdotgg#9561 fix(ui): unify loading and refresh feedback across clients (pingdotgg#9561) pingdotgg#10226 refactor(web): keep feature component helpers private (pingdotgg#10226) pingdotgg#9754 feat(settings): add shared project defaults and scoped overrides (pingdotgg#9754) pingdotgg#9895 feat(connections): balance new threads across connected machines (pingdotgg#9895) pingdotgg#10273 fix(mobile): stop the work log flickering during subagent runs and failing calls (pingdotgg#10273) pingdotgg#10271 fix(mobile): save linked media from chat (pingdotgg#10271) ... 90 more; --json lists every source. ``` `--json` returns the same 16 paths and all 110 sources. `early 5521 --through upstream/main`, which plans successfully, prints the same summary as before. --- Written by an agent (Claude Code, claude-opus-5-5).
Stacked on #10211.
Problem
Opening a row's details inside an expanded tool group left an unpainted band the size of the growth (88 points for a five-line command output). Layout was correct everywhere — LegendList's sizes, the outer row's measured height, and accessibility frames all matched — but the pixels for everything past the group's old bottom edge were missing until the group was collapsed and reopened.
The group's scroll-edge fades come from
@expo/ui'sMaskedView, which hosts the list inside a SwiftUI.maskviaRNHostView. That host keeps the bounds it had when the mask was built, so a resize clips the tail. #9359 worked around the first symptom by forcing the list's height; this is the second.Confirmed by elimination on the simulator: removing layout animations, the inner
ScrollView,selectable,absoluteFill, andmaintainVisibleContentPositioneach left the band in place; swappingMaskedViewfor a plain clippedViewremoved it.Fix
overflow: hiddenview and draw the fades as two screen-colored SVG gradients over the edges, each fading in only while content continues past that edge (same scroll-offset math, inverted from "cover" to "fade"). The screen color comes fromThreadFeed, which already reads the theme.totalSizesignal instead of the nativeonContentSizeChange, so the outer row resizes in the same commit as the row measurement that changed it.ShimmeringWorkContentstill usesMaskedView; its mask never resizes.Verification
tsc --noEmitforapps/mobile, targeted lint and format.mainand this branch. The blank band after expanding theffmpegrow: 88 points → 0. Fades verified on a 12-call group: bottom fade present at offset 0, top fade present when scrolled to the end, both painted in the screen color.Recording of the expand/collapse, before on the left:
https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f0dfbe332a6d42b8/stack-pair-expand.mp4
Implemented by Claude Fable 5 in the Claude Code harness.
Note
Fix clipped expanded tool groups and settle workflow coordinator members in thread activity
MaskedViewcomposite mask inThreadWorkGroupListwith a clipped container and separate animatedEdgeFadeoverlays that fade only at edges with remaining content, using the current screen theme colorThreadFeedandThreadWorkLogso edge fades match the backgroundisAgentInternalActivityto retain task lifecycle rows with a task identifier and agent kind for batch processing instead of filtering them as internalagentSpawnRow, a terminal workflow coordinator now settles members that lack their own end event or remain in progress; explicitly reported member statuses are preservedtoDerivedWorkLogEntrywhen no other lifecycle status is presentThreadWorkGroupListnow uses a ref callback subscribing to LegendList total-size updates instead of the native content-size callback; verify scroll fade visibility and content-height bookkeeping remain correct under rapid resize and theme switchesMacroscope summarized 65b1b9c.