fix(gallery): paginate media, activity log and export on detached timeline sets — never the live timeline (#163)
RoomTimeline renders a numeric index window into the live timeline's event arrays; SDK back-pagination prepends, so any side panel calling paginateEventTimeline(room.getLiveTimeline()) shifted the visible messages into the past on the next render and broke at-bottom tracking. New utils/detachedTimeline.ts builds a timeline set that mirrors the already-loaded history and paginates independently: a room-registered filtered set (server-side contains_url / types filter) when the filter is usable, else a private EventTimelineSet seeded from the live timeline. useRoomMediaTimeline wraps it for the gallery (live events + redactions handled); RoomActivityLog uses a type filter (safe in encrypted rooms); ExportRoomHistory pages a private set so a full export no longer parks thousands of events in the live timeline. Verified with Playwright against a local Synapse in a 400-message plain room and a 200-message encrypted room: timeline stays at the bottom through gallery pages, activity load-more and a full export; live messages keep auto-scrolling; all media found in both rooms. Also adds scripts/dev-homeserver.sh + scripts/dev-seed.py (local throwaway Synapse for driving the real UI) and documents them. Closes #163 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
@@ -4,6 +4,7 @@ import { EventType } from 'matrix-js-sdk';
|
||||
import { Page, PageContent, PageHeader } from '../../components/page';
|
||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||
import { useRoom } from '../../hooks/useRoom';
|
||||
import { createDetachedTimelineSet } from '../../utils/detachedTimeline';
|
||||
import { useRoomName } from '../../hooks/useRoomMeta';
|
||||
import { SequenceCard } from '../../components/sequence-card';
|
||||
import { SequenceCardStyle } from '../common-settings/styles.css';
|
||||
@@ -73,7 +74,10 @@ export function ExportRoomHistory({ requestClose }: ExportRoomHistoryProps) {
|
||||
// so we must deduplicate by eventId to avoid re-adding the same events
|
||||
// on each pagination step.
|
||||
const seen = new Set<string>();
|
||||
const timeline = room.getLiveTimeline();
|
||||
// [Gitea #163] Paginate a private timeline set, not the live one: the
|
||||
// export can pull thousands of events and the room behind this modal
|
||||
// renders the live timeline by index.
|
||||
const timeline = createDetachedTimelineSet(mx, room).set.getLiveTimeline();
|
||||
let canLoadMore = true;
|
||||
// Track the oldest collected timestamp incrementally so the fromTs check
|
||||
// doesn't rescan the whole `collected` array on every pagination step.
|
||||
|
||||
Reference in New Issue
Block a user