Files
llink/js/desktop
Claude af69f98583 feat(desktop): paginate stream particles via windowed Firestore subscription
Streams previously prefetched every particle through an unbounded Firestore
subscription. This adds a windowed source that anchors a `created_at desc`
limit query at the newest particle and grows it backward on demand, so the
already-seen history before a viewer's playback marker is no longer loaded.

- `useWindowedStreamParticles`: tail-anchored live window that grows backward
  to cover the resume marker and to service `loadOlder()` (list scroll-up).
  Because the window always includes the newest particle, new arrivals stream
  in and forward playback never needs a fetch. Includes anti-eviction growth
  so a new tail particle never pushes loaded particles out of the window.
- `useStreamPlayback`: consumes the windowed source instead of loading all
  children. New-tail and removal handling are derived from the children array
  (Firestore change events can't tell a genuine arrival from pagination
  backfill). Resume-from-marker waits for backward growth to reach an older
  marker; `prev` at the window edge pulls in older history.

Playback resume, forward-only marker persistence, auto-advance-on-new, and
removal fallback are all preserved. List view and progress indicator continue
to render off the (now windowed) children; their pagination UX is a follow-up.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V8gsmdVd7R8PJtn4UFnC4J
2026-06-21 01:54:39 +00:00
..
2026-05-26 15:37:35 -07:00
2026-05-26 15:37:35 -07:00
2026-05-26 15:41:54 -07:00
2026-05-26 15:37:35 -07:00
2026-06-09 09:12:03 -07:00
2026-05-26 15:37:35 -07:00

Notes

CORS for desktop app

In dev: each renderer process has its own localhost port. The renderer process passes this in the Origin header for requests, and expects appropriate ACAO headers in the response.

In packaged app: the renderer process does not include Origin header, so expects no extra ACAO headers from the server, otherwise the client would fail to accept responses.