Skip to content

SwiftUI: reveal message timestamps on swipe - #8620

Open
saphid wants to merge 4 commits into
pingdotgg:t3code/rebuild-mobile-app-swiftfrom
saphid:swiftui/pr-112-timestamps
Open

SwiftUI: reveal message timestamps on swipe#8620
saphid wants to merge 4 commits into
pingdotgg:t3code/rebuild-mobile-app-swiftfrom
saphid:swiftui/pr-112-timestamps

Conversation

@saphid

@saphid saphid commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

What Changed

  • Adds a deliberate leftward pan in the SwiftUI transcript to reveal the local sent or received time for every visible user and assistant message.
  • Moves the visible transcript as one bounded sheet, keeps each timestamp aligned to its message, and returns the transcript to rest on release or cancellation.
  • Keeps the reveal stable while messages stream or the collection view applies a snapshot. If the transcript was following the bottom, it stays there and refreshes timestamp anchors after scrolling.
  • Preserves message-view identity through streaming completion. VoiceOver exposes the same timestamp through accessibility custom content.
  • Limits the change to the SwiftUI client. Server contracts, web, desktop, and React Native mobile are unchanged.

The implementation and focused tests stay in the existing transcript owner:

  • apps/swift-ios/Features/Chat/ThreadDetailView.swift
  • apps/swift-ios/Tests/FeatureTests/TranscriptViewportGeometryTests.swift

Why

The SwiftUI client had no quick way to inspect several message times in context. The reveal belongs at the transcript boundary because the collection view already owns visible-row geometry, scrolling, snapshot completion, and gesture arbitration.

The pan recognizer accepts one finger and requires clear horizontal intent. It yields to vertical scrolling, selectable Markdown, and nested horizontal scrollers such as code blocks. The reveal resets when the gesture ends or when a thread update leaves no eligible messages.

This supersedes #5820. PR 8620 is based on t3code/rebuild-mobile-app-swift at b67837984e5650888b1eed0e1cd7fff83625f696; the current head is bfb058405a28d78e87eec3923475720180744507.

UI Changes

The previous media links were removed because anonymous GET requests returned HTTP 404 pages. Older issue-112 captures also predate the three follow-up fixes on this PR and are not current-head proof.

The replacement packet is blocked on a SwiftUI proof lease. At the latest atomic allocation attempt, all three contracted simulator slots were active:

  • Lane 1: pr-7453-proof-refresh
  • Lane 2: non-git-dot-entry-visibility
  • Lane 3: pr-7399-proof-refresh

No simulator was taken and no lease was bypassed.

When a slot is free, the replacement packet will be captured from exact base b67837984 and exact head bfb058405 using the repository timeline workflow:

  1. Capture dark mode first, with matching light-mode evidence.
  2. Keep each raw recording immutable. Record a leftward horizontal swipe with enough lead-in to show the resting transcript and enough tail to show the complete return state.
  3. Derive matching clean and annotated MP4s, posters, contact sheets, tight phone-readable screenshots, and cropped GIFs from the timeline.
  4. Make the primary motion proof show the touch moving right to left, legible timestamps during the reveal, and the timestamp-free resting state after release.
  5. Embed tight dark-mode media first, keep matching full-window context collapsed, and put all light-mode media in one collapsed section.
  6. Publish media outside the product diff and verify every anonymous URL with a successful GET and the expected image or video content type after it appears in the live PR body.

Review fixes already on this head

  • 6d96bd988 keeps message identity and timestamp anchors through streaming completion.
  • e87bce8fc restores the bottom position during a reveal when the transcript is following the latest message.
  • bfb058405 refreshes timestamp anchors after that scroll completes.

All four review threads are resolved. Cursor Bugbot's latest review completed successfully. Macroscope's correctness check passed; its approvability check still calls for human review because this is a substantial transcript interaction.

Verification

  • GitHub CI Check: passed on bfb058405.
  • GitHub CI Test: passed on bfb058405.
  • SwiftUI iOS Contract fixtures and native tests: passed on bfb058405.
  • Cursor Bugbot: passed on bfb058405.
  • Macroscope correctness: passed on bfb058405.
  • git diff --check: clean locally.
  • Live PR audit: mergeable, maintainer edits enabled, all review threads resolved.

Risks and limitations

  • The diff is size:XL because it adds the transcript interaction and focused geometry, gesture, anchoring, streaming, and accessibility coverage. It is one SwiftUI-only outcome, but it is not a small patch.
  • Gesture competition, bottom anchoring, snapshot updates, streaming completion, Reduce Motion, and VoiceOver are the main risk areas.
  • Exact-head integrated media remains missing until a proof slot is released. The PR should not be treated as evidence-complete or ready for human review before the replacement packet is embedded and every URL is checked from the live body.
  • Preview jobs for unrelated web, desktop, and React Native surfaces are skipped by path gating.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included current-head before/after screenshots for the UI change
  • I included a current-head video for the interaction
  • The branch contains no media or generated proof artifacts
  • Every validation result above reflects the current PR head

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 75305a26-1569-4b26-9d68-bd93d33773e9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Aug 29, 2026
Comment thread apps/swift-ios/Features/Chat/ThreadDetailView.swift Outdated
Comment thread apps/swift-ios/Features/Chat/ThreadDetailView.swift
@macroscopeapp

macroscopeapp Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This adds a substantial user-facing iOS transcript interaction involving gesture arbitration, row overlays, streaming updates, accessibility, and bottom-anchor scrolling. Its production behavior extends well beyond a small isolated UI tweak, so the interaction and scrolling impact should receive human review.

You can add or adjust custom eligibility rules. Learn more.

…eveal

Two review findings on the swipe-to-reveal timestamps feature:

Eligibility (streaming -> complete) decided a structural branch around the
message view, so completing a stream rebuilt the row and dropped
MarkdownMessageView's @State, breaking its streaming -> complete promote
path. The message view now sits at one fixed structural position and only
the timestamp overlay is conditional; the accessibility modifier branches
on role, which never changes, and announces an empty value while a message
is still streaming.

Dismissing the reveal zeroed the anchors immediately, so timestamps faded
out while drifting to their row midpoints and the transcript re-anchored
mid-dismissal. beginDismissal() now only zeroes the width; the anchors
survive the slide-back and are cleared by the release animation's
completion, guarded by a generation counter so a stale completion cannot
settle a newer gesture. The collection view mirrors
timestampReveal.isActive on every update so resets that bypass the
completion cannot leave the bottom-anchor suppression stuck on.

Co-Authored-By: Claude <noreply@anthropic.com>
Comment thread apps/swift-ios/Features/Chat/ThreadDetailView.swift

@cursor cursor Bot left a comment

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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e87bce8. Configure here.

Comment thread apps/swift-ios/Features/Chat/ThreadDetailView.swift
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL 500-999 changed lines (additions + deletions). 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