Skip to content

feat(v2): load older messages in pod chat - #767

Merged
lilyshen0722 merged 1 commit into
mainfrom
feat/pod-load-older-messages
Jul 28, 2026
Merged

feat(v2): load older messages in pod chat#767
lilyshen0722 merged 1 commit into
mainfrom
feat/pod-load-older-messages

Conversation

@lilyshen0722

Copy link
Copy Markdown
Contributor

Reported: "the load older messages thing works on the public-read showcase room but it doesn't work on a real entered pod."

It was never built there

Not a broken feature. #764 added paging to the showcase reader only. The authenticated path fired exactly one request and kept no cursor:

// useV2PodDetail.ts — the complete message-read implementation, before
api.get(`/api/messages/${id}?limit=50`)   // no before, no hasMore, no loadOlder

V2PodChat had no button, no scroll handler, no observer. So any conversation past 50 messages was simply unreachable in a pod you had joined.

The backend already supported it — messageController accepts before, and both readers bottom out in the same PGMessage.findByPodId. The whole gap was client-side.

What's here

  • useV2PodDetail gains hasMore / loadingOlder / loadOlder. End-of-history is inferred from a short page, because this endpoint returns a bare array and adding an envelope would break every existing consumer.
  • Pages merge by id, not concat — the socket can deliver a message mid-flight and a concat would duplicate it.
  • The pager renders at the top of the scroll container, styled to match the showcase pill so both reading surfaces agree.
  • i18n keys in en and zh-CN.

Two scroll defects that would have made it look broken

  1. The auto-scroll effect keyed on messages.length, so prepending a page threw the reader from the older message they'd just asked for straight back to the bottom. Now keyed on the newest message's id, so prepends are ignored.
  2. A prepend changes scrollHeight and jumps the viewport. The reader's position is held by restoring distance-from-bottom, which is invariant under a prepend.

Neither is visible to jsdom, which is why they're called out rather than assumed fixed.

Test

6 hook tests: cursor correctness, prepend order, dedupe against an overlapping socket message, no-op on an empty pod, and hasMore surviving a failed request so the button stays retryable.

Frontend suite 69/69 suites, 316 tests. Lint identical to baseline (163 problems, the 1 error pre-existing in PersonalityBuilder.tsx). Typecheck: one pre-existing error remains, one removed.

Wants a real-browser check after deploy — per CLAUDE.md, jsdom has no layout engine, and the scroll-anchor behaviour above is exactly the class of thing it can't cover.

🤖 Generated with Claude Code

"Load older messages" worked on the anonymous showcase route but did nothing in
a pod you had actually joined. Not a broken feature — it was never built there.
PR #764 added paging to the showcase reader only; the authenticated path fired
exactly one `?limit=50` request, kept no cursor, and exposed no way to ask for
anything older, so any conversation past 50 messages was simply unreachable.

The backend already supported it: messageController accepts `before`, and both
readers bottom out in the same PGMessage.findByPodId. The entire gap was
client-side.

- useV2PodDetail gains hasMore / loadingOlder / loadOlder. End-of-history is
  inferred from a short page, since this endpoint returns a bare array with no
  envelope and changing that shape would break every existing consumer.
- Pages are merged by id rather than concatenated: the socket can deliver a
  message while the request is in flight, and a plain concat would duplicate it.
- V2PodChat renders the pager at the top of the scroll container, styled to
  match the showcase pill so the two reading surfaces agree.

Two scroll defects had to be fixed or the feature would have looked broken:

- the auto-scroll effect keyed on `messages.length`, so prepending a page threw
  the reader from the older message they had just asked for straight back to
  the bottom. It now keys on the newest message's id, so prepends are ignored.
- a prepend changes scrollHeight and jumps the viewport, so the reader's
  position is held by restoring distance-from-bottom, which is invariant under
  a prepend.

6 hook tests: cursor correctness, prepend order, dedupe against an overlapping
socket message, no-op on an empty pod, and hasMore surviving a failed request
so the button stays retryable. Frontend suite 69/69, 316 tests. Lint at
baseline.

Needs a real-browser check after deploy — jsdom has no layout engine, so the
scroll-anchor behaviour specifically is not covered by these tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DMeWzgFxsfBcjoLVLewEES
@lilyshen0722
lilyshen0722 merged commit 69b6005 into main Jul 28, 2026
11 checks passed
@lilyshen0722
lilyshen0722 deleted the feat/pod-load-older-messages branch July 28, 2026 00:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant