Skip to content

Sync chat timeline and mobile UX#133

Merged
aaditagrawal merged 6 commits into
mainfrom
sync/upstream-20260701-chat-mobile
Jul 3, 2026
Merged

Sync chat timeline and mobile UX#133
aaditagrawal merged 6 commits into
mainfrom
sync/upstream-20260701-chat-mobile

Conversation

@aaditagrawal

@aaditagrawal aaditagrawal commented Jul 1, 2026

Copy link
Copy Markdown
Owner

What Changed

Ports chat scroll anchoring, timeline minimap and affordances, right-panel middle-click close, ultrathink CSS restoration, and mobile composer revision-gated updates.

Why

This aligns the fork with upstream chat timeline and mobile UX fixes while keeping the sync work reviewable as a separate stack slice.

UI Changes

Includes upstream chat timeline, right-panel, CSS, and mobile composer UI behavior updates.

Checklist

  • Part 4 of the upstream sync stack
  • Validation on stack tip: vp check
  • Validation on stack tip: vp run typecheck
  • Validation on stack tip: vp run lint:mobile
  • Full vp test had one ACP timeout flake; rerunning that file passed

@aaditagrawal aaditagrawal mentioned this pull request Jul 1, 2026
5 tasks
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@aaditagrawal, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 56 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 02623558-aae5-4168-b991-a1b5f985ac5c

📥 Commits

Reviewing files that changed from the base of the PR and between a7ca68e and feb7380.

📒 Files selected for processing (21)
  • apps/mobile/modules/t3-composer-editor/ios/T3ComposerEditorModule.swift
  • apps/mobile/modules/t3-composer-editor/ios/T3ComposerEditorView.swift
  • apps/mobile/src/features/threads/ThreadFeed.tsx
  • apps/mobile/src/features/threads/thread-work-log.tsx
  • apps/mobile/src/lib/threadActivity.test.ts
  • apps/mobile/src/lib/threadActivity.ts
  • apps/mobile/src/native/T3ComposerEditor.ios.tsx
  • apps/mobile/src/native/composerEditorRevision.test.ts
  • apps/mobile/src/native/composerEditorRevision.ts
  • apps/web/src/components/BranchToolbar.tsx
  • apps/web/src/components/ChatView.tsx
  • apps/web/src/components/RightPanelTabs.tsx
  • apps/web/src/components/chat/ChatComposer.tsx
  • apps/web/src/components/chat/ComposerBannerStack.tsx
  • apps/web/src/components/chat/MessagesTimeline.logic.test.ts
  • apps/web/src/components/chat/MessagesTimeline.logic.ts
  • apps/web/src/components/chat/MessagesTimeline.test.tsx
  • apps/web/src/components/chat/MessagesTimeline.tsx
  • apps/web/src/components/chat/timelineScrollAnchoring.test.tsx
  • apps/web/src/components/chat/timelineScrollAnchoring.ts
  • apps/web/src/index.css
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sync/upstream-20260701-chat-mobile

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

aaditagrawal commented Jul 1, 2026

Copy link
Copy Markdown
Owner Author

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL 1,000+ effective changed lines (test files excluded in mixed PRs). labels Jul 1, 2026
@aaditagrawal aaditagrawal changed the title Sync chat timeline mobile UX Sync chat timeline and mobile UX Jul 1, 2026
@aaditagrawal
aaditagrawal marked this pull request as ready for review July 2, 2026 12:53
@aaditagrawal

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 730be69678

ℹ️ 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 thread apps/web/src/components/ChatView.tsx
Comment thread apps/web/src/components/ChatView.tsx Outdated
scrollNode.addEventListener("touchmove", handleManualNavigation, {
passive: true,
});
scrollNode.addEventListener("pointerdown", handleManualNavigation, {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid cancelling live follow on ordinary clicks

Because pointerdown bubbles from all controls inside the scroll node, clicking a copy button, link, disclosure, or message area while a response is streaming calls cancelTimelineLiveFollowForUserNavigation() even though no scroll gesture occurred. In the anchored-send path maintainScrollAtEnd is disabled, so after such a click subsequent tokens stop auto-following and the user can be left behind the live edge unexpectedly.

Useful? React with 👍 / 👎.

Comment on lines 224 to 225
const onToggleTurnFold = useCallback((turnId: TurnId) => {
setFoldToggleSettling(true);
setExpandedTurnIds((existing) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Suspend end anchoring when toggling turn folds

This fold toggle now only mutates expandedTurnIds, while the list below keeps maintainScrollAtEnd enabled whenever there is no active anchoredEndSpace. When a user expands/collapses a "Worked for…" fold while already at the live edge, LegendList can re-pin the bottom as rows are inserted/removed above the terminal message, pulling the fold control out of view; the previous settling guard handled exactly this case and was removed without an equivalent for turn folds.

Useful? React with 👍 / 👎.

Comment thread apps/web/src/components/chat/MessagesTimeline.tsx
@aaditagrawal
aaditagrawal force-pushed the sync/upstream-20260701-chat-mobile branch from 730be69 to 4798ab9 Compare July 2, 2026 13:23

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4798ab9fd6

ℹ️ 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 thread apps/web/src/components/ChatView.tsx
@aaditagrawal
aaditagrawal force-pushed the sync/upstream-20260701-chat-mobile branch from 4798ab9 to 6258f37 Compare July 2, 2026 14:15
@aaditagrawal
aaditagrawal force-pushed the sync/upstream-20260701-preview branch from d4cdb21 to 5f0839b Compare July 2, 2026 14:15

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6258f37f9e

ℹ️ 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 thread apps/web/src/components/ChatView.tsx
Comment on lines +697 to +700
"group/minimap pointer-events-auto absolute top-0 left-0 z-40 hidden w-18 [@media(pointer:fine)]:block",
hasPersistentGutter
? "opacity-100"
: "opacity-0 transition-opacity duration-150 hover:opacity-100 focus-within:opacity-100",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid letting the hidden minimap steal message clicks

When the viewport is too narrow for a persistent gutter (hasPersistentGutter is false for common desktop widths below the helper's 864px threshold), this minimap is only made transparent, but it remains pointer-events-auto and is absolutely placed over the left edge of the timeline. In conversations with at least two user messages, the invisible rail/button can intercept clicks, link activation, and text selection in the first ~50px of assistant content until the user happens to hover it, which makes normal message interaction fail in that strip.

Useful? React with 👍 / 👎.

@aaditagrawal
aaditagrawal force-pushed the sync/upstream-20260701-preview branch from 5f0839b to ead5a2c Compare July 2, 2026 17:47
@aaditagrawal
aaditagrawal force-pushed the sync/upstream-20260701-chat-mobile branch from 6258f37 to eeacb89 Compare July 2, 2026 17:47

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eeacb895c2

ℹ️ 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 thread apps/web/src/components/ChatView.tsx Outdated
Comment thread apps/web/src/components/ChatView.tsx Outdated
Comment on lines +3314 to +3316
scrollNode.addEventListener("wheel", handleManualNavigation, {
passive: true,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Gate wheel cancellation on vertical timeline movement

When a response is streaming, any wheel event bubbling to the timeline cancels live-follow, even if the wheel gesture is consumed by a nested horizontal scroller such as an overflowing code block/diff or is otherwise not moving the vertical list. In that case the user has not navigated away from the live edge, but subsequent tokens can stop auto-following; check the wheel delta/scroll target or cancel only after an actual timeline scroll.

Useful? React with 👍 / 👎.

Comment thread apps/mobile/src/features/threads/ThreadFeed.tsx

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eeacb895c2

ℹ️ 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 thread apps/web/src/components/chat/MessagesTimeline.tsx
row.kind === "message" ? row.message.id : null,
),
[anchorMessageId, rows],
const minimapItems = useMemo(() => deriveTimelineMinimapItems(rows), [rows]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid building hidden minimap previews while streaming

This computes minimap previews on every rows change even when TimelineMinimap will immediately return null for threads with fewer than two user messages. During a first large streaming response, each token update changes rows, then deriveTimelineMinimapItems scans the row list and compactMinimapPreview regex-copies the full assistant text even though no minimap can render; gate this work on having enough user rows or compute preview text lazily/truncated.

Useful? React with 👍 / 👎.

Comment thread apps/web/src/components/chat/MessagesTimeline.tsx
@aaditagrawal
aaditagrawal force-pushed the sync/upstream-20260701-chat-mobile branch from eeacb89 to 51615cb Compare July 2, 2026 18:31
@aaditagrawal
aaditagrawal force-pushed the sync/upstream-20260701-preview branch 2 times, most recently from 244ad30 to 35a7c5c Compare July 2, 2026 18:34
@aaditagrawal
aaditagrawal force-pushed the sync/upstream-20260701-chat-mobile branch from 51615cb to 261c515 Compare July 2, 2026 18:34

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 261c51535c

ℹ️ 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 thread apps/web/src/components/ChatView.tsx Outdated
Comment on lines +3354 to +3355
if (pendingTimelineAnchorRef.current !== messageId) {
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Clear stale anchor after live-follow cancellation

With this guard now in place, a user who scrolls away immediately after sending can leave timelineAnchor.messageId stuck: the cancellation path clears pendingTimelineAnchorRef, so this branch returns without ever clearing the React anchor state. MessagesTimeline still derives anchoredEndSpace from that prop and disables maintainScrollAtEnd while it is present, so that thread can keep reserved anchor space/end-following disabled until another send or thread switch. Clear the timeline anchor here, or when cancelling the pending anchor.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 88b1735e36

ℹ️ 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 thread apps/web/src/components/ChatView.tsx Outdated
useEffect(() => {
let removeListeners: (() => void) | null = null;
let frame: number | null = null;
let attemptsRemaining = 60;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep retrying until the timeline mounts

The new finite retry still leaves empty threads without the manual-navigation listeners if the user opens a new empty thread and waits more than about a second before sending the first prompt: while the placeholder is rendered getScrollableNode() stays null, the loop exhausts, and this effect will not rerun when rows appear because it only depends on activeThread?.id. During that first streamed response, wheel/touch/key scrolls are then treated as live-follow programmatic movement and can be suppressed, so the list can snap back to the end instead of letting the user read earlier content.

Useful? React with 👍 / 👎.

isAtEndRef.current = true;
timelineScrollModeRef.current = "anchoring-new-turn";
liveFollowUserScrollGenerationRef.current = anchorUserScrollGenerationRef.current;
pendingTimelineAnchorRef.current = messageIdForSend;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Clear pending anchors when send cleanup removes the row

If the send/start path fails before onAnchorReady runs and the failure cleanup removes this optimistic message, this pending anchor is never cleared because the missing row cannot fire onReady. The live-follow effect bails out while pendingTimelineAnchorRef is non-null, so after a failed send the thread can stop following new output until the user navigates or sends again; clear the pending/timeline anchor in the failure cleanup that removes messageIdForSend.

Useful? React with 👍 / 👎.

@aaditagrawal
aaditagrawal force-pushed the sync/upstream-20260701-preview branch from 8216039 to 61135b3 Compare July 3, 2026 08:16
@aaditagrawal
aaditagrawal force-pushed the sync/upstream-20260701-chat-mobile branch from 8e8ba2e to 9ee152a Compare July 3, 2026 08:17
@aaditagrawal
aaditagrawal force-pushed the sync/upstream-20260701-preview branch from 61135b3 to acee6f6 Compare July 3, 2026 08:18
@aaditagrawal
aaditagrawal force-pushed the sync/upstream-20260701-chat-mobile branch from 9ee152a to 931ea0a Compare July 3, 2026 08:19
@aaditagrawal
aaditagrawal changed the base branch from sync/upstream-20260701-preview to graphite-base/133 July 3, 2026 08:19
@graphite-app
graphite-app Bot changed the base branch from graphite-base/133 to main July 3, 2026 08:20
@aaditagrawal
aaditagrawal force-pushed the sync/upstream-20260701-chat-mobile branch from 931ea0a to 53ee88c Compare July 3, 2026 08:20
@aaditagrawal
aaditagrawal force-pushed the sync/upstream-20260701-chat-mobile branch from 53ee88c to feb7380 Compare July 3, 2026 08:20
@aaditagrawal
aaditagrawal merged commit b23c6b3 into main Jul 3, 2026
11 checks passed

Copy link
Copy Markdown
Owner Author

Merge activity

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

Labels

size:XXL 1,000+ effective changed lines (test files excluded in mixed PRs). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant