Repository navigation
Conversation
Restore the native editor offset after expansion and keep the caret visible following text and selection changes. Preserve manual scrolling on unchanged documents and typography rebuilds. Add focused UIKit regression checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a focused iOS composer bug fix that preserves scroll position and caret visibility during existing resize, focus, and text-update flows. Runtime changes are confined to the existing native editor, while the other three files add only a local regression harness; no defaults or static-analysis suppressions are changed. You can add or adjust custom eligibility rules. Learn more. |
|
Thanks for this fix. #23096 includes your commit unchanged, with you as the author. It adds one more change on top: on the simulator, the tap that reopens the collapsed composer still moved the caret to the first line, so the view went back to the top even with the offset restored. #23096 keeps the caret where you left it for long drafts, and has before/after recordings from the app. |
Problem
A long iOS thread draft can reopen at its first line after the editor loses focus, leaving the caret off-screen. Rebuilding the attributed document for programmatic text updates also fails to explicitly keep the new caret position visible.
Change
Preserve the native editor's scroll offset before disabling scrolling or rebuilding its attributed text, then restore and clamp it after layout. Reveal the caret rectangle after expansion, text edits, and explicit selection changes. Unchanged controlled documents and typography-only rebuilds preserve manual scrolling.
The production change adds 43 lines in
T3ComposerEditorView.swift. The accompanying UIKit regression runner compiles the production editor with stubbed Expo module plumbing, following the existing native Mac Catalyst test approach.Scope and approval
Fixes #22006.
This qualifies as a focused fix of an obvious bug: native scroll state is lost during resize and the editor does not maintain caret visibility. Composer heights, line counts, focus rules, and collapse behavior stay unchanged. Sizing and fullscreen editing remain out of scope per #21126. The change stays local to the iOS view to minimize overlap with #20812.
Android was inspected and left unchanged: its
setScrollEnabledonly toggles scrollbar visibility, so it does not share the iOS scrolling-disable root cause. Web, desktop, providers, contracts, and connection behavior are unaffected.Verification
On macOS arm64 with Node 24 and Xcode 27.0:
vp i— completed successfully; no dependency or lockfile changes.vp run --filter @t3tools/mobile typecheck— passed.vp test run apps/mobile/src/native/composerEditorRevision.test.ts apps/mobile/src/features/voice-input/voiceInputSession.test.ts apps/mobile/src/features/threads/use-composer-command-menu.test.ts— 52 tests passed across three files.apps/mobile/modules/t3-composer-editor/tests/run-ios.sh— 26/26 UIKit checks passed. The same runner against the original editor from48b486bd73855c109735e84337735658700b0599fails 12 assertions (14/26 pass). Checks cover both resize/prop orders, offset restoration, controlled and native insertion, explicit caret moves, unchanged documents, typography rebuilds, collapsed updates, and clearing the draft.vp lint apps/mobile/src/features/threads/ThreadComposer.tsx apps/mobile/src/native/T3ComposerEditor.ios.tsx— exited 0, with 11 existing React warnings in these unchanged files.vp run lint:mobile— SwiftLint, ktlint, and detekt passed.swiftlint lint --strict --config apps/mobile/.swiftlint.yml apps/mobile/modules/t3-composer-editor/ios/T3ComposerEditorView.swift apps/mobile/modules/t3-composer-editor/tests/ios/ExpoModulesCore.swift apps/mobile/modules/t3-composer-editor/tests/ios/main.swift— zero violations.bash -n apps/mobile/modules/t3-composer-editor/tests/run-ios.shandgit diff --check— passed.Simulator evidence: iPhone 17 Pro, iOS 27.0. A standalone native harness compiles the production editor unchanged, with the Expo view, event dispatchers, and unused clipboard helpers stubbed. It drives a 40-line draft through focus, scroll to the end, blur/collapse (36 pt, scrolling disabled), refocus/expand (160 pt, scrolling enabled), controlled insertion, and native
insertText.On the baseline, refocus resets offset
640 → 0; the caret aty=779is off-screen. With this fix, refocus retains offset640and the caret is visible. Controlled insertion and native typing at the end remain visible afterward, at offset720. Those insertions also settle visibly on the baseline in this focused simulator harness; the immediate programmatic-update failure is demonstrated by the Catalyst regression checks.Before refocus:
After refocus:
Before recording · After recording · After insertion screenshot · After typing screenshot
Baseline measurements · Fixed measurements · Baseline regression log · Fixed regression log · Harness source · Harness runner
Evidence and harness files live only on the fork's separate orphan branch
pr-assets/ios-composer-scroll-22006; no PR-only assets are included in this diff.Limits: full Expo/React Native app verification is incomplete.
node scripts/mobile-native-client.ts ensure ios 4722D760-7249-4D16-B3F6-7F64939CB126completed prebuild but stopped atpod installwithspawn pod ENOENTbecause CocoaPods is missing. T3's Device panel also returned “Agent device access is turned off for this environment.” The captures show native focus/blur and resize; the software keyboard is not displayed. Actual dictation, React Native prop scheduling, physical-device behavior, and the issue reporter's iOS 27.2 beta were not verified.Implemented with GPT-6.1-Sol (Codex) in T3 Code, orchestrated by Claude Opus 5.5 (Claude Code).
🤖 Generated with Claude Code