fix pagination

This commit is contained in:
tezlm 2023-12-09 20:19:02 -08:00
parent 7a553917ed
commit b9f6b82611
Signed by: tezlm
GPG key ID: 649733FCD94AFBBA
5 changed files with 112 additions and 126 deletions

View file

@ -5,22 +5,25 @@ import { Thread } from "./thread.js";
export interface Timeline {
isLive: boolean;
events: Array<Event>;
paginate(dir: "f" | "b", limit: number): Promise<boolean>;
}
export declare class RoomTimeline implements Timeline {
room: Room;
events: Array<Event>;
isLive: boolean;
prevBatch: string | null;
nextBatch: string | null;
prevBatch: string | null | undefined;
nextBatch: string | null | undefined;
constructor(room: Room);
paginate(dir: "f" | "b", limit?: number): Promise<boolean>;
}
export declare class ThreadTimeline implements Timeline {
thread: Thread;
events: Array<Event>;
isLive: boolean;
prevBatch: string | null;
nextBatch: string | null;
prevBatch: string | null | undefined;
nextBatch: string | null | undefined;
constructor(thread: Thread);
paginate(dir: "f" | "b", limit?: number): Promise<boolean>;
}
export declare class TimelineSet {
room: Room;
@ -28,6 +31,5 @@ export declare class TimelineSet {
private timelines;
constructor(room: Room);
forEvent(eventId: EventId): Promise<RoomTimeline>;
paginate(timeline: Timeline, dir: "f" | "b", limit?: number): Promise<boolean>;
_appendEvents(events: Array<Event>): void;
}

113
dist/src/timeline.js vendored
View file

@ -33,6 +33,30 @@ export class RoomTimeline {
value: null
});
}
async paginate(dir, limit = 50) {
const from = (dir === "f" ? this.nextBatch : this.prevBatch) || undefined; // FIXME: don't paginate at ends
const data = await this.room.client.net.fetchMessages({
roomId: this.room.id,
dir,
limit,
from,
});
if (dir === "f") {
const events = data.chunk.map(raw => new Event(this.room, raw));
this.nextBatch = data.end || null;
this.events.push(...events);
for (const event of events)
this.room.events.set(event.id, event);
}
else {
const events = data.chunk.reverse().map(raw => new Event(this.room, raw));
this.prevBatch = data.end || null;
this.events.push(...events);
for (const event of events)
this.room.events.set(event.id, event);
}
return true;
}
}
export class ThreadTimeline {
constructor(thread) {
@ -58,15 +82,39 @@ export class ThreadTimeline {
enumerable: true,
configurable: true,
writable: true,
value: null
value: undefined
});
Object.defineProperty(this, "nextBatch", {
enumerable: true,
configurable: true,
writable: true,
value: null
value: undefined
});
}
async paginate(dir, limit = 50) {
const { room } = this.thread;
const from = (dir === "f" ? this.nextBatch : this.prevBatch) || undefined; // FIXME: don't paginate at ends
const data = await room.client.net.fetchRelations(room.id, this.thread.baseEvent.id, {
dir,
from,
limit,
});
if (dir === "f") {
const events = data.chunk.map(raw => new Event(room, raw));
this.nextBatch = data.next_batch || null;
this.events.push(...events);
for (const event of events)
room.events.set(event.id, event);
}
else {
const events = data.chunk.map(raw => new Event(room, raw));
this.prevBatch = data.prev_batch || null;
this.events.push(...events);
for (const event of events)
room.events.set(event.id, event);
}
return true;
}
}
export class TimelineSet {
// private eventIdToTimeline: Map<EventId, Timeline> = new Map();
@ -115,67 +163,6 @@ export class TimelineSet {
this.timelines.add(tl);
return tl;
}
// Paginate a timeline for more events
// TODO: fuse two neighboring timelines together
// TODO: don't bother paginating if a timeline is at the end
// NOTE: whether a thread starts at the beginning or end depends on whether it's first paginated with "b" or "f"
async paginate(timeline, dir, limit = 50) {
const { net } = this.room.client;
if (timeline instanceof ThreadTimeline) {
const from = (dir === "f" ? timeline.nextBatch : timeline.prevBatch) || undefined;
if (!from)
return false;
const data = await net.fetchRelations(this.room.id, timeline.thread.baseEvent.id, {
dir,
from,
limit,
});
if (dir === "f") {
const events = data.chunk.map(raw => new Event(this.room, raw));
timeline.nextBatch = data.next_batch;
timeline.events.push(...events);
for (const event of events)
this.room.events.set(event.id, event);
}
else {
const events = data.chunk.map(raw => new Event(this.room, raw));
timeline.prevBatch = data.prev_batch;
timeline.events.push(...events);
for (const event of events)
this.room.events.set(event.id, event);
}
return true;
}
else if (timeline instanceof RoomTimeline) {
const from = (dir === "f" ? timeline.nextBatch : timeline.prevBatch) || undefined;
if (!from)
return false;
const data = await net.fetchMessages({
roomId: this.room.id,
dir,
limit,
from,
});
if (dir === "f") {
const events = data.chunk.map(raw => new Event(this.room, raw));
timeline.nextBatch = data.end;
timeline.events.push(...events);
for (const event of events)
this.room.events.set(event.id, event);
}
else {
const events = data.chunk.reverse().map(raw => new Event(this.room, raw));
timeline.prevBatch = data.end;
timeline.events.push(...events);
for (const event of events)
this.room.events.set(event.id, event);
}
return true;
}
else {
throw new Error("todo");
}
}
_appendEvents(events) {
// FIXME: there should only be one live timeline for each room and
// thread, they need to be merged together

View file

@ -1 +1 @@
{"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../src/timeline.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../src/timeline.ts"],"names":[],"mappings":"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"}

File diff suppressed because one or more lines are too long

View file

@ -14,17 +14,44 @@ export interface Timeline {
// the events in this timeline
events: Array<Event>,
// Paginate a timeline for more events
// TODO: fuse two neighboring timelines together
// TODO: don't bother paginating if a timeline is at the end
paginate(dir: "f" | "b", limit: number): Promise<boolean>;
}
export class RoomTimeline implements Timeline {
public events: Array<Event> = [];
public isLive: boolean = false;
prevBatch: string | null = null;
nextBatch: string | null = null;
prevBatch: string | null | undefined = null;
nextBatch: string | null | undefined = null;
constructor(public room: Room) {}
public async paginate(dir: "f" | "b", limit: number = 50): Promise<boolean> {
const from = (dir === "f" ? this.nextBatch : this.prevBatch) || undefined; // FIXME: don't paginate at ends
const data = await this.room.client.net.fetchMessages({
roomId: this.room.id,
dir,
limit,
from,
});
if (dir === "f") {
const events = data.chunk.map(raw => new Event(this.room, raw));
this.nextBatch = data.end || null;
this.events.push(...events);
for (const event of events) this.room.events.set(event.id, event);
} else {
const events = data.chunk.reverse().map(raw => new Event(this.room, raw));
this.prevBatch = data.end || null;
this.events.push(...events);
for (const event of events) this.room.events.set(event.id, event);
}
return true;
}
// concat(other: RoomTimeline): RoomTimeline {
// if (this.events.length === 0) return other;
// if (other.events.length === 0) return this;
@ -37,10 +64,32 @@ export class ThreadTimeline implements Timeline {
public events: Array<Event> = [];
public isLive: boolean = false;
prevBatch: string | null = null;
nextBatch: string | null = null;
prevBatch: string | null | undefined = undefined;
nextBatch: string | null | undefined = undefined;
constructor(public thread: Thread) {}
public async paginate(dir: "f" | "b", limit: number = 50): Promise<boolean> {
const { room } = this.thread;
const from = (dir === "f" ? this.nextBatch : this.prevBatch) || undefined; // FIXME: don't paginate at ends
const data = await room.client.net.fetchRelations(room.id, this.thread.baseEvent.id, {
dir,
from,
limit,
});
if (dir === "f") {
const events = data.chunk.map(raw => new Event(room, raw));
this.nextBatch = data.next_batch || null;
this.events.push(...events);
for (const event of events) room.events.set(event.id, event);
} else {
const events = data.chunk.map(raw => new Event(room, raw));
this.prevBatch = data.prev_batch || null;
this.events.push(...events);
for (const event of events) room.events.set(event.id, event);
}
return true;
}
}
export class TimelineSet {
@ -78,58 +127,6 @@ export class TimelineSet {
return tl;
}
// Paginate a timeline for more events
// TODO: fuse two neighboring timelines together
// TODO: don't bother paginating if a timeline is at the end
// NOTE: whether a thread starts at the beginning or end depends on whether it's first paginated with "b" or "f"
public async paginate(timeline: Timeline, dir: "f" | "b", limit: number = 50): Promise<boolean> {
const { net } = this.room.client;
if (timeline instanceof ThreadTimeline) {
const from = (dir === "f" ? timeline.nextBatch : timeline.prevBatch) || undefined;
if (!from) return false;
const data = await net.fetchRelations(this.room.id, timeline.thread.baseEvent.id, {
dir,
from,
limit,
});
if (dir === "f") {
const events = data.chunk.map(raw => new Event(this.room, raw));
timeline.nextBatch = data.next_batch;
timeline.events.push(...events);
for (const event of events) this.room.events.set(event.id, event);
} else {
const events = data.chunk.map(raw => new Event(this.room, raw));
timeline.prevBatch = data.prev_batch;
timeline.events.push(...events);
for (const event of events) this.room.events.set(event.id, event);
}
return true;
} else if (timeline instanceof RoomTimeline) {
const from = (dir === "f" ? timeline.nextBatch : timeline.prevBatch) || undefined;
if (!from) return false;
const data = await net.fetchMessages({
roomId: this.room.id,
dir,
limit,
from,
});
if (dir === "f") {
const events = data.chunk.map(raw => new Event(this.room, raw));
timeline.nextBatch = data.end;
timeline.events.push(...events);
for (const event of events) this.room.events.set(event.id, event);
} else {
const events = data.chunk.reverse().map(raw => new Event(this.room, raw));
timeline.prevBatch = data.end;
timeline.events.push(...events);
for (const event of events) this.room.events.set(event.id, event);
}
return true;
} else {
throw new Error("todo");
}
}
_appendEvents(events: Array<Event>) {
// FIXME: there should only be one live timeline for each room and
// thread, they need to be merged together