Skip to content

fix(mobile): hide scroll-to-end button while dragging at the bottom - #11854

Closed
zero-two-rafaeltab wants to merge 3 commits into
pingdotgg:mainfrom
zero-two-rafaeltab:t3code/fix-android-bottom-button
Closed

zero-two-rafaeltab wants to merge 3 commits into
pingdotgg:mainfrom
zero-two-rafaeltab:t3code/fix-android-bottom-button

Conversation

@zero-two-rafaeltab

@zero-two-rafaeltab zero-two-rafaeltab commented Sep 15, 2026 •

Copy link
Copy Markdown

Problem and fix

Dragging further down while already at the bottom of a mobile thread briefly shows the scroll-to-end button. Starting a drag intentionally pauses live-follow before the list moves, and the button previously used that pause alone as its visibility condition. The list already handles overscroll with a <= end-distance check.

Show the button only when live-follow is paused and the list is away from the end. Subscribe to LegendList's end-position transitions, including layout changes, while preserving the existing live-follow behavior and avoiding state updates on every scroll frame.

Validation

  • Added regression tests before the fix: two failed on the old visibility condition; all 30 focused tests pass with the fix.
  • Mobile TypeScript check and targeted formatting pass. Targeted lint passes with existing React warnings.
  • Built and tested T3 Code Dev on an Android 16 emulator against an isolated server with seeded thread content.
  • Verified dragging further down at the bottom keeps the button hidden, scrolling up shows it, and tapping it returns to the bottom and hides it.
  • Shared Android/iOS thread-view change; iOS was not run. No web, desktop, provider, or wire-contract changes. No user workflow or documentation changes.

Before / after

New recordings show the same full sequence in both versions, with Android Show touches and Pointer location enabled:

  • 0–7 seconds: already at the bottom, try scrolling farther down. The button appears before the fix and stays hidden after it.
  • 7–12 seconds: scroll up normally, then pause. The button appears in both versions.
  • 12–17 seconds: tap the button to return to the bottom; it disappears.
  • 17–22 seconds: try scrolling farther down at the bottom again.

Watch the side-by-side video · Before video · After video

Dragging farther down at the bottom:

Before and after at the bottom

After scrolling up normally — the button is visible in both versions:

Before and after scrolling up

Model: GPT-6. Harness: Codex.

Duplicate check and platform scope

  • #6232 (fix(mobile): stabilize scroll-to-end control) was an earlier PR for this same regression: the scroll-to-end button briefly appeared when a drag started at the actual end because the live-follow latch was the only visibility condition. Its proposed fix also gated the button on both paused live-follow and the feed being away from the end.
  • fix(mobile): stabilize scroll-to-end control #6232 was closed unmerged on September 7 during the open-PR backlog sweep. The closing note says the mobile live-follow helpers had already landed and points to later scroll fixes (fix(mobile): stabilize thread composer and interactions #5986 / fix(mobile): wait for native thread scroll before reveal #10486), with an invitation to reopen/rebase if this behavior was still wanted. This PR revisits the same fix against current main, with the end-state subscription also covering layout changes.
  • Based on the shared ThreadFeed/ThreadDetailScreen and LegendList path, iOS should receive this fix too; it is not Android-specific. The Android/iOS differences in this area are keyboard and content-inset handling, not the end-follow visibility rule. The bug was reproduced on Android 16; iOS was not run, so iOS verification remains outstanding.

Summary by CodeRabbit

  • New Features

    • Improved the thread feed’s scroll-to-end button behavior based on the user’s current position and live-follow state.
    • The button now appears only after scrolling away from the end and remains hidden while live-following content.
  • Tests

    • Added coverage for scroll-to-end visibility during dragging, scrolling, and streaming updates.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Sep 15, 2026
@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Sep 15, 2026
@github-actions github-actions Bot added size:M 30-99 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Sep 15, 2026
@zero-two-rafaeltab
zero-two-rafaeltab marked this pull request as ready for review September 15, 2026 16:08
@coderabbitai

coderabbitai Bot commented Sep 15, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 2945ee2b-4e0b-439f-8118-a85e51ebf62c

📥 Commits

Reviewing files that changed from the base of the PR and between 5623089 and 9cc7992.

📒 Files selected for processing (4)
  • apps/mobile/src/features/threads/ThreadDetailScreen.tsx
  • apps/mobile/src/features/threads/ThreadFeed.tsx
  • apps/mobile/src/features/threads/thread-feed-live-follow.test.ts
  • apps/mobile/src/features/threads/thread-feed-live-follow.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The thread feed now reports whether it is at the end. The detail screen tracks this state and uses it with live-follow state to control the scroll-to-end button.

Changes

Thread feed end-position tracking

Layer / File(s) Summary
Live-follow visibility rule
apps/mobile/src/features/threads/thread-feed-live-follow.ts, apps/mobile/src/features/threads/thread-feed-live-follow.test.ts
Adds shouldShowThreadFeedScrollToEnd and tests its behavior for live-follow and end-position states.
Feed position reporting
apps/mobile/src/features/threads/ThreadFeed.tsx
Adds onIsAtEndChange and reports LegendList end-position changes at mount, during transitions, and after disclosure layout settles.
Detail screen integration
apps/mobile/src/features/threads/ThreadDetailScreen.tsx
Tracks and resets isAtEnd, passes the callback to ThreadFeed, and shows the scroll-to-end button only when the feed is ready, not live-following, and not at the end.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: juliusmarminge

Merge Risk: ⚪ Minimal · up to 9cc79

The scroll-to-end visibility update is ready to merge with no identified current-head risk.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 4 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main mobile bug fix: hiding the scroll-to-end button while dragging at the bottom.
Description check ✅ Passed The description explains the problem, fix, validation, UI behavior, platform scope, and supporting video evidence. It omits the template checklist and uses different section headings, but the required…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@zero-two-rafaeltab

Copy link
Copy Markdown
Author

Review follow-up for 9cc7992265bfbee1d8423ea69c1da128b1116914:

  • CodeRabbit has completed its current-head review with no actionable findings and minimal merge risk. There are no unresolved review threads.
  • Re-ran the focused mobile scroll tests: all 30 pass. The current code reconciles end position after disclosure layout settles as well as on list edge transitions.
  • Leaving the advisory docstring-coverage warning unaddressed: the repository's AGENTS.md asks us not to document every function or repeat implementation already clear from the source. The non-obvious distinction between pausing live-follow and leaving the bottom already has a nearby comment. Adding boilerplate to reach a coverage percentage would work against that guidance.

The remaining merge blocker is workflow approval, not a failed test. CI for this commit is action_required; required checks Test, Check, Mobile Native Static Analysis, and Release Smoke have not run. A repository maintainer needs to approve the pending fork workflows before their results can be assessed. The contributor account cannot approve upstream workflow runs.

return;
}
onIsAtEndChange(listState.isAtEnd);
return listState.listen("isAtEnd", onIsAtEndChange);

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.

🟡 Medium threads/ThreadFeed.tsx:2433

When a row grows from asynchronous measurement or streaming without a scroll event, the parent keeps isAtEnd: true even though the reader is above the end, so shouldShowThreadFeedScrollToEnd stays hidden. This subscription only observes LegendList's stored observable; size-only changes require querying getState(). Update the parent from getState().isAtEnd in onItemSizeChanged for all row resizes, not only during disclosure settling.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/mobile/src/features/threads/ThreadFeed.tsx around line 2433:

When a row grows from asynchronous measurement or streaming without a scroll event, the parent keeps `isAtEnd: true` even though the reader is above the end, so `shouldShowThreadFeedScrollToEnd` stays hidden. This subscription only observes LegendList's stored observable; size-only changes require querying `getState()`. Update the parent from `getState().isAtEnd` in `onItemSizeChanged` for all row resizes, not only during disclosure settling.

@macroscopeapp

macroscopeapp Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — This is a narrow, tested mobile UI bug fix that changes only scroll-to-end button visibility and leaves existing live-follow behavior intact, with no schema, security, billing, or infrastructure impact. An unresolved Medium finding identifies a possible stale end-state after non-disclosure row resizing, which remains a follow-up risk despite the otherwise limited scope.

Not approved because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge

Copy link
Copy Markdown
Member

Thanks for working on this. We merged the orchestrator V2 rewrite in #2829, and we are closing this PR as part of that transition.

The patch conflicts with the rewrite in apps/mobile/src/features/threads/ThreadFeed.tsx. Even where the conflict is small enough to rebase, we are asking for fresh PRs against the new base so we can review and verify the behavior in V2.

Sorry for the extra work this creates. If the change is still needed on V2, please rebuild it on current main, verify it there, and open a new PR linking back here. We're closing the current implementation without assuming the underlying request is resolved.

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

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants