Skip to content

feat(swift-ios): reveal message timestamps on swipe - #5820

Open
saphid wants to merge 5 commits into
pingdotgg:t3code/rebuild-mobile-app-swiftfrom
saphid:t3code/swiftui-swipe-message-timestamps
Open

feat(swift-ios): reveal message timestamps on swipe#5820
saphid wants to merge 5 commits into
pingdotgg:t3code/rebuild-mobile-app-swiftfrom
saphid:t3code/swiftui-swipe-message-timestamps

Conversation

@saphid

@saphid saphid commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

What Changed

  • Reveal each visible SwiftUI transcript message's local sent or received time while the user drags the transcript left.
  • Drive all visible rows from one bounded reveal distance, then return the thread to rest on release or cancellation.
  • Preserve vertical scrolling, keyboard dismissal, and nested horizontal Markdown scrollers; respect Reduce Motion and expose the timestamps to VoiceOver.

This is intentionally SwiftUI-only. It does not change the server, wire contracts, web/desktop client, or React Native mobile client.

Why

Conversation timestamps currently require opening individual message details. This gives the native iOS client the familiar iMessage interaction: a deliberate leftward drag reveals several message times in context without leaving the thread.

The implementation stays at the transcript's existing UICollectionView ownership seam. A dedicated pan recognizer publishes one small observable reveal value to the virtualized visible cells, while gesture arbitration leaves vertical transcript scrolling and nested horizontal content intact.

Base: t3code/rebuild-mobile-app-swift at f98cab553546558e28d6e22f3dbe9807ecc3325f.

UI Changes

Before During left drag
Thread before timestamp reveal Five message times revealed

Interaction

Two message times revealed on the final head

Play the 7-second final-head MP4

The recording uses a real 1.5-second swipe against the integrated app on commit c4bb0cf8d, with two message times visible together; it is not a staged animation.

Verification

  • Current-head Contract fixtures and native tests CI job — passed on c4bb0cf8d, including the previously failing environment-scoped provider fixtures.
  • Focused native suites on iPhone 17 Pro / iOS 26.5 — 13 tests passed, zero failures: all five HomeThreadMetadataTests and all eight TranscriptViewportGeometryTests.
  • Exact-head build, install, and launch — passed for com.t3tools.t3code.swiftui.dev on iOS 26.5.
  • Integrated SwiftUI simulator pass on iOS 26.5 — a real left drag revealed two distinct timestamps (11:47 pm and 11:49 pm) together and they disappeared at rest. LLDB measured translation x = -94 and velocity = (-207.29, 0) on the timestamp pan; the vertical-dismissal guard evaluated false.
  • git diff --check — passed.
  • The fixture repair is test-only and patch-identical to direct upstream PR test(swift-ios): use environment-scoped provider catalogs #6130; it updates stale fixtures to the environment-scoped provider catalog introduced by Theo's target without changing timestamp-swipe production behavior.
  • Independent Claude Opus 5 high review found one real layout issue: the hidden timestamp could enlarge short rows. Replacing the sizing ZStack with a non-sizing overlay preserves the approved reveal appearance and fixes the resting row height; the already-required user doc is now indexed.
  • Cursor's valid ready-state finding that a noisy horizontal pan could arm keyboard dismissal is fixed on c4bb0cf8d; the focused regression and exact-head gesture both verify horizontal intent does not enter that path, and the review thread is resolved with evidence.
  • A fresh frozen-head Claude Opus 5 high review was launched for c4bb0cf8d, but exited 1 before producing a verdict because the Anthropic session limit was reached; no current-head Opus verdict is claimed. The earlier successful Opus review remains recorded above.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Built with GPT-5.6 Sol in the Codex harness.

Note

Add swipe-to-reveal message timestamps in the iOS chat transcript view

  • Adds a leftward pan gesture on the chat transcript that slides messages left to reveal a trailing timestamp label, animating closed when the gesture ends.
  • Introduces FeatureTimestampRevealState, FeatureTimestampRevealMessageView, and TranscriptTimestampRevealGeometry in ThreadDetailView.swift to manage reveal state, geometry clamping, and gesture gating.
  • Gesture only activates on deliberate leftward horizontal pans and yields to nested horizontal scrollers via UIGestureRecognizerDelegate.
  • Adds FeatureMessageTimestampAccessibilityModifier so VoiceOver users receive timestamp information as custom accessibility content on all message types.
  • Keyboard dismissal and bottom-anchor release are deferred until meaningful vertical scroll movement is detected, replacing the previous keyboardDismissMode = .onDrag approach.

Macroscope summarized ad0b3dd. (Automatic summaries will resume when PR exits draft mode or review begins).


Note

Low Risk
SwiftUI/UIKit transcript interaction only; no server or data changes, with geometry covered by unit tests.

Overview
Adds iMessage-style swipe-to-reveal timestamps on the native iOS chat transcript: a leftward pan drives one shared reveal distance so visible rows slide left and show trailing hour/minute labels, then animate closed on release (honoring Reduce Motion).

The transcript UICollectionView coordinator owns a non-cancelling pan recognizer with gesture arbitration—only deliberate leftward horizontal pans, simultaneous recognition with scrolling, and deferral when the touch hits nested horizontal scrollers (e.g. wide Markdown). Collection cells wrap messages in FeatureTimestampRevealMessageView backed by shared FeatureTimestampRevealState and TranscriptTimestampRevealGeometry for clamping.

Keyboard and scroll behavior changes: keyboardDismissMode = .onDrag is removed; keyboard dismissal and releasing the bottom anchor now run only after meaningful vertical movement in scrollViewDidScroll. VoiceOver gets sent/received timestamp custom content on all message roles via FeatureMessageTimestampAccessibilityModifier.

Unit tests cover reveal width bounds and pan direction gating in TranscriptViewportGeometryTests.

Reviewed by Cursor Bugbot for commit ad0b3dd. Bugbot is set up for automated code reviews on this repo. Configure here.

Delivery: direct
Validated against Theo commit: f98cab5
Depends on: none
Merge order: this PR only
Validation status: Ready for human review. Current-head actionable CI, Cursor, Macroscope correctness, focused native tests, and integrated Simulator validation pass; zero unresolved threads. Macroscope approvability is neutral because new features require human review. The unrelated Vercel authorization failure is a maintainer-side gate.

@coderabbitai

coderabbitai Bot commented Aug 9, 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: 97bca958-d365-4abc-a979-df7055a21181

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

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.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 9, 2026
@saphid
saphid marked this pull request as ready for review August 9, 2026 11:10
@macroscopeapp

macroscopeapp Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing feature (swipe-to-reveal timestamps) with new gesture handling, UI components, and state management. New features with this scope warrant human review.

You can customize Macroscope's approvability policy. Learn more.

@saphid

saphid commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

@t3dotgg This SwiftUI PR is ready for your review. Its exact head is mergeable; repository/native CI, MacroScope, Cursor, and review-thread audits are clean with zero unresolved threads. The only red status is the unrelated Vercel marketing authorization check.

@t3dotgg
t3dotgg force-pushed the t3code/rebuild-mobile-app-swift branch from 4cb3307 to 497f54f Compare August 10, 2026 03:58
@saphid

saphid commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

Dependency-safe rebuild is preserved at saphid/swiftui-timestamp-final-stack (7832b2f3f), one unique commit on the frozen editor/reasoning/keyboard + orange integration base. Do not force-update this Theo-targeted PR yet because doing so would duplicate those open foundations.

Conflict classification: stale code/history, not duplicate feature. One semantic repair was required: the old commit removed native .keyboardDismissMode = .onDrag; the rebuild retains accepted keyboard behavior. Timestamp pan is bounded/left-horizontal, yields to nested scrollers, never performs an action/full swipe, settles to zero, resets on reuse/teardown, preserves links/text selection/long-press/settle swipe, supports Reduce Motion, and exposes VoiceOver timestamp content.

Verification: focused 10/10; full native xcresult 365 total / 364 pass / one expected skip / zero fail; signed Debug run; integrated mixed rows/link/timestamp swipe/software-keyboard vertical dismissal/long-press proof; git diff --check clean. Tailnet-only video: https://alexs-macbook-pro-1.tail4e5636.ts.net:10016/timestamp-final-proof.mp4

Evidence limitation: automation hid the visible software keyboard before the left-swipe segment, so the video does not conclusively show keyboard remaining open during timestamp reveal; source/gesture ordering tests cover non-dismissal and the video separately proves keyboard open + scoped vertical dismissal. Landing: editor/reasoning/keyboard foundations and #5972 first, then transplant only 7832b2f3f. Opus unavailable at confirmed 429; no verdict claimed.

@saphid
saphid marked this pull request as draft August 10, 2026 14:44
@github-actions github-actions Bot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 10, 2026
@saphid
saphid force-pushed the t3code/swiftui-swipe-message-timestamps branch from ad0b3dd to a651dc6 Compare August 11, 2026 10:26
@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Aug 11, 2026
@saphid

saphid commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

Final-head conflict check (a651dc6): native text selection still presents handles and the edit menu on the timestamp implementation, so the horizontal timestamp recognizer does not steal selection.

Text selection preserved on final timestamp head

The focused timestamp/viewport suite passed (7/7). A new exact-head velocity reveal could not be captured with the semantic driver; the existing real-drag GIF in the PR remains the visual timestamp proof. The current native-CI red is the base fixture failure fixed in #6130.

@saphid
saphid marked this pull request as ready for review August 12, 2026 13:28

@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.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 9a0d36a. Configure here.

Comment thread apps/swift-ios/Features/Chat/ThreadDetailView.swift
@saphid
saphid marked this pull request as draft August 12, 2026 13:39
@saphid
saphid marked this pull request as ready for review August 12, 2026 14:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 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