Add timeline pagination
This commit is contained in:
parent
20b78d0bea
commit
14acca5b62
17 changed files with 175 additions and 37 deletions
8
dist/src/net.d.ts
vendored
8
dist/src/net.d.ts
vendored
|
@ -19,13 +19,13 @@ export declare class Network {
|
||||||
roomId: t.RoomId;
|
roomId: t.RoomId;
|
||||||
dir: "b" | "f";
|
dir: "b" | "f";
|
||||||
limit?: number;
|
limit?: number;
|
||||||
from: string;
|
from?: string;
|
||||||
to?: string;
|
to?: string;
|
||||||
}): Promise<t.MessagesResponse>;
|
}): Promise<t.MessagesResponse>;
|
||||||
fetchRelations(roomId: t.RoomId, eventId: t.EventId, opts: {
|
fetchRelations(roomId: t.RoomId, eventId: t.EventId, opts: {
|
||||||
relType?: string;
|
relType?: string;
|
||||||
eventType?: string;
|
eventType?: string;
|
||||||
limit?: string;
|
limit?: number;
|
||||||
dir: "b" | "f";
|
dir: "b" | "f";
|
||||||
from?: string;
|
from?: string;
|
||||||
to?: string;
|
to?: string;
|
||||||
|
@ -34,8 +34,8 @@ export declare class Network {
|
||||||
from?: string;
|
from?: string;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
roomIds?: Array<t.RoomId>;
|
roomIds?: Array<t.RoomId>;
|
||||||
watching: boolean;
|
watching?: boolean;
|
||||||
include: Array<t.IncludeThreads>;
|
include?: Array<t.IncludeThreads>;
|
||||||
}): Promise<t.ThreadsResponse>;
|
}): Promise<t.ThreadsResponse>;
|
||||||
fetchInbox(opts: {
|
fetchInbox(opts: {
|
||||||
roomIds?: Array<t.RoomId>;
|
roomIds?: Array<t.RoomId>;
|
||||||
|
|
8
dist/src/net.js
vendored
8
dist/src/net.js
vendored
|
@ -91,7 +91,9 @@ export class Network {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async fetchMessages(opts) {
|
async fetchMessages(opts) {
|
||||||
let path = `/_matrix/client/v3/rooms/${e(opts.roomId)}/messages?limit=${opts.limit || 50}&from=${e(opts.from)}&dir=${e(opts.dir)}`;
|
let path = `/_matrix/client/v3/rooms/${e(opts.roomId)}/messages?limit=${opts.limit || 50}&dir=${e(opts.dir)}`;
|
||||||
|
if (opts.from)
|
||||||
|
path += `&from=${e(opts.from)}`;
|
||||||
if (opts.to)
|
if (opts.to)
|
||||||
path += `&to=${e(opts.to)}`;
|
path += `&to=${e(opts.to)}`;
|
||||||
return this.fetch({ method: "GET", path });
|
return this.fetch({ method: "GET", path });
|
||||||
|
@ -114,7 +116,7 @@ export class Network {
|
||||||
async fetchThreads(opts) {
|
async fetchThreads(opts) {
|
||||||
return this.fetch({
|
return this.fetch({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
path: `/_matrix/client/v1/threads?limit=${opts.limit}${opts.from ? `&from=${e(opts.from)}` : ""}`,
|
path: `/_matrix/client/v1/threads?limit=${opts.limit || 50}${opts.from ? `&from=${e(opts.from)}` : ""}`,
|
||||||
body: {
|
body: {
|
||||||
watching: opts.watching,
|
watching: opts.watching,
|
||||||
room_ids: opts.roomIds,
|
room_ids: opts.roomIds,
|
||||||
|
@ -125,7 +127,7 @@ export class Network {
|
||||||
async fetchInbox(opts) {
|
async fetchInbox(opts) {
|
||||||
return this.fetch({
|
return this.fetch({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
path: `/_matrix/client/v1/inbox?limit=${opts.limit}${opts.from ? `&from=${e(opts.from)}` : ""}`,
|
path: `/_matrix/client/v1/inbox?limit=${opts.limit || 50}${opts.from ? `&from=${e(opts.from)}` : ""}`,
|
||||||
body: {
|
body: {
|
||||||
filter: opts.filter,
|
filter: opts.filter,
|
||||||
room_ids: opts.roomIds,
|
room_ids: opts.roomIds,
|
||||||
|
|
2
dist/src/net.js.map
vendored
2
dist/src/net.js.map
vendored
File diff suppressed because one or more lines are too long
5
dist/src/room.d.ts
vendored
5
dist/src/room.d.ts
vendored
|
@ -1,8 +1,9 @@
|
||||||
import TypedEmitter from "typed-emitter";
|
import TypedEmitter from "typed-emitter";
|
||||||
import { ApiEphemeralEvent, SyncResponseRoom, Unreads } from "./api.js";
|
import { ApiEphemeralEvent, EventId, SyncResponseRoom, Unreads } from "./api.js";
|
||||||
import { Client } from "./client.js";
|
import { Client } from "./client.js";
|
||||||
import { Event, StateEvent } from "./event.js";
|
import { Event, StateEvent } from "./event.js";
|
||||||
import { TimelineSet } from "./timeline.js";
|
import { TimelineSet } from "./timeline.js";
|
||||||
|
import { Thread } from "./thread.js";
|
||||||
type RoomEvents = {
|
type RoomEvents = {
|
||||||
timeline: (event: Event) => void;
|
timeline: (event: Event) => void;
|
||||||
ephemeral: (event: ApiEphemeralEvent) => void;
|
ephemeral: (event: ApiEphemeralEvent) => void;
|
||||||
|
@ -20,6 +21,8 @@ export declare class Room extends Room_base {
|
||||||
id: string;
|
id: string;
|
||||||
private state;
|
private state;
|
||||||
timelines: TimelineSet;
|
timelines: TimelineSet;
|
||||||
|
events: Map<EventId, Event>;
|
||||||
|
threads: Map<EventId, Thread>;
|
||||||
constructor(client: Client, id: string, data: SyncResponseRoom);
|
constructor(client: Client, id: string, data: SyncResponseRoom);
|
||||||
_merge(data: SyncResponseRoom): void;
|
_merge(data: SyncResponseRoom): void;
|
||||||
getState(type: string, stateKey?: string): StateEvent | null;
|
getState(type: string, stateKey?: string): StateEvent | null;
|
||||||
|
|
16
dist/src/room.js
vendored
16
dist/src/room.js
vendored
|
@ -44,6 +44,18 @@ export class Room extends EventEmitter {
|
||||||
writable: true,
|
writable: true,
|
||||||
value: void 0
|
value: void 0
|
||||||
});
|
});
|
||||||
|
Object.defineProperty(this, "events", {
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
writable: true,
|
||||||
|
value: new Map()
|
||||||
|
});
|
||||||
|
Object.defineProperty(this, "threads", {
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
writable: true,
|
||||||
|
value: new Map()
|
||||||
|
});
|
||||||
this.timelines = new TimelineSet(this);
|
this.timelines = new TimelineSet(this);
|
||||||
this.timelines.live.prevBatch = data.prev_batch || null;
|
this.timelines.live.prevBatch = data.prev_batch || null;
|
||||||
this._merge(data);
|
this._merge(data);
|
||||||
|
@ -71,12 +83,12 @@ export class Room extends EventEmitter {
|
||||||
getAllState(type) {
|
getAllState(type) {
|
||||||
return [...this.state.get(type)?.values() ?? []];
|
return [...this.state.get(type)?.values() ?? []];
|
||||||
}
|
}
|
||||||
// TODO: return event
|
// TODO: local echo, return event
|
||||||
async sendState(type, stateKey, content) {
|
async sendState(type, stateKey, content) {
|
||||||
// const { event_id } = await this.client.net.sendState(this.id, type, stateKey, content);
|
// const { event_id } = await this.client.net.sendState(this.id, type, stateKey, content);
|
||||||
await this.client.net.sendState(this.id, type, stateKey, content);
|
await this.client.net.sendState(this.id, type, stateKey, content);
|
||||||
}
|
}
|
||||||
// TODO: return event
|
// TODO: local echo(?), return event
|
||||||
async sendEvent(type, content) {
|
async sendEvent(type, content) {
|
||||||
await this.client.net.sendEvent(this.id, type, nanoid(), content);
|
await this.client.net.sendEvent(this.id, type, nanoid(), content);
|
||||||
}
|
}
|
||||||
|
|
2
dist/src/room.js.map
vendored
2
dist/src/room.js.map
vendored
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"room.js","sourceRoot":"","sources":["../../src/room.ts"],"names":[],"mappings":"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"}
|
{"version":3,"file":"room.js","sourceRoot":"","sources":["../../src/room.ts"],"names":[],"mappings":"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"}
|
1
dist/src/thread.d.ts
vendored
1
dist/src/thread.d.ts
vendored
|
@ -10,6 +10,7 @@ declare const Thread_base: new () => TypedEmitter<ThreadEvents>;
|
||||||
export declare class Thread extends Thread_base {
|
export declare class Thread extends Thread_base {
|
||||||
baseEvent: Event;
|
baseEvent: Event;
|
||||||
room: Room;
|
room: Room;
|
||||||
|
timeline: null;
|
||||||
constructor(baseEvent: Event);
|
constructor(baseEvent: Event);
|
||||||
}
|
}
|
||||||
export {};
|
export {};
|
||||||
|
|
6
dist/src/thread.js
vendored
6
dist/src/thread.js
vendored
|
@ -14,6 +14,12 @@ export class Thread extends EventEmitter {
|
||||||
writable: true,
|
writable: true,
|
||||||
value: this.baseEvent.room
|
value: this.baseEvent.room
|
||||||
});
|
});
|
||||||
|
Object.defineProperty(this, "timeline", {
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
writable: true,
|
||||||
|
value: null
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//# sourceMappingURL=thread.js.map
|
//# sourceMappingURL=thread.js.map
|
2
dist/src/thread.js.map
vendored
2
dist/src/thread.js.map
vendored
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"thread.js","sourceRoot":"","sources":["../../src/thread.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAclC,MAAM,OAAO,MAAO,SAAS,YAAgE;IAG3F,YAAmB,SAAgB;QACjC,KAAK,EAAE,CAAC;QADE;;;;mBAAO,SAAS;WAAO;QAF5B;;;;mBAAa,IAAI,CAAC,SAAS,CAAC,IAAI;WAAC;IAIxC,CAAC;CACF"}
|
{"version":3,"file":"thread.js","sourceRoot":"","sources":["../../src/thread.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAclC,MAAM,OAAO,MAAO,SAAS,YAAgE;IAI3F,YAAmB,SAAgB;QACjC,KAAK,EAAE,CAAC;QADE;;;;mBAAO,SAAS;WAAO;QAH5B;;;;mBAAa,IAAI,CAAC,SAAS,CAAC,IAAI;WAAC;QACjC;;;;mBAAiB,IAAI;WAAC;IAI7B,CAAC;CACF"}
|
3
dist/src/timeline.d.ts
vendored
3
dist/src/timeline.d.ts
vendored
|
@ -16,7 +16,7 @@ export declare class RoomTimeline implements Timeline {
|
||||||
}
|
}
|
||||||
export declare class ThreadTimeline implements Timeline {
|
export declare class ThreadTimeline implements Timeline {
|
||||||
thread: Thread;
|
thread: Thread;
|
||||||
events: never[];
|
events: Array<Event>;
|
||||||
isLive: boolean;
|
isLive: boolean;
|
||||||
prevBatch: string | null;
|
prevBatch: string | null;
|
||||||
nextBatch: string | null;
|
nextBatch: string | null;
|
||||||
|
@ -28,5 +28,6 @@ export declare class TimelineSet {
|
||||||
private timelines;
|
private timelines;
|
||||||
constructor(room: Room);
|
constructor(room: Room);
|
||||||
forEvent(eventId: EventId): Promise<RoomTimeline>;
|
forEvent(eventId: EventId): Promise<RoomTimeline>;
|
||||||
|
paginate(timeline: Timeline, dir: "f" | "b", limit?: number): Promise<boolean>;
|
||||||
_appendEvents(events: Array<Event>): void;
|
_appendEvents(events: Array<Event>): void;
|
||||||
}
|
}
|
||||||
|
|
66
dist/src/timeline.js
vendored
66
dist/src/timeline.js
vendored
|
@ -116,13 +116,71 @@ export class TimelineSet {
|
||||||
return tl;
|
return tl;
|
||||||
}
|
}
|
||||||
// Paginate a timeline for more events
|
// Paginate a timeline for more events
|
||||||
// public paginate(timeline: Timeline, dir: "f" | "b", limit: number = 50) {
|
// TODO: fuse two neighboring timelines together
|
||||||
// throw "todo";
|
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) {
|
_appendEvents(events) {
|
||||||
// FIXME: merge timelines together
|
// FIXME: merge timelines together
|
||||||
|
for (const event of events)
|
||||||
|
this.room.events.set(event.id, event);
|
||||||
for (const timeline of this.timelines) {
|
for (const timeline of this.timelines) {
|
||||||
if (timeline.isLive)
|
// if (timeline.isLive) timeline.events.push(...events);
|
||||||
|
if (timeline.isLive && timeline instanceof RoomTimeline)
|
||||||
timeline.events.push(...events);
|
timeline.events.push(...events);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
dist/src/timeline.js.map
vendored
2
dist/src/timeline.js.map
vendored
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../src/timeline.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAK7C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAQnC,MAAM,OAAO,YAAY;IAOvB,YAAmB,IAAU;QAAjB;;;;mBAAO,IAAI;WAAM;QANtB;;;;mBAAuB,EAAE;WAAC;QAC1B;;;;mBAAkB,KAAK;WAAC;QAE/B;;;;mBAA2B,IAAI;WAAC;QAChC;;;;mBAA2B,IAAI;WAAC;IAIhC,CAAC;CAQF;AAED,MAAM,OAAO,cAAc;IAOzB,YAAmB,MAAc;QAArB;;;;mBAAO,MAAM;WAAQ;QAN1B;;;;mBAAS,EAAE;WAAC;QACZ;;;;mBAAkB,KAAK;WAAC;QAE/B;;;;mBAA2B,IAAI;WAAC;QAChC;;;;mBAA2B,IAAI;WAAC;IAEI,CAAC;CACtC;AAED,MAAM,OAAO,WAAW;IAItB,iEAAiE;IAEjE,YAAmB,IAAU;QAAjB;;;;mBAAO,IAAI;WAAM;QAL7B,uEAAuE;QAChE;;;;;WAAmB;QAClB;;;;mBAA2B,IAAI,GAAG,EAAE;WAAC;QAI3C,IAAI,CAAC,IAAI,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,0EAA0E;IAC1E,sFAAsF;IACtF,kBAAkB;IAClB,oCAAoC;IACpC,8CAA8C;IAC9C,kBAAkB;IAClB,IAAI;IAEJ,yCAAyC;IAClC,KAAK,CAAC,QAAQ,CAAC,OAAgB;QACpC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC/E,MAAM,EAAE,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,EAAE,CAAC,MAAM,GAAG,OAAO,CAAC,aAAa;aAC9B,OAAO,EAAE;aACT,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;aACvB,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC;aAC5B,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QACzC,EAAE,CAAC,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC;QAC7B,EAAE,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC;QAC3B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,sCAAsC;IACtC,4EAA4E;IAC5E,kBAAkB;IAClB,IAAI;IAEJ,aAAa,CAAC,MAAoB;QAChC,kCAAkC;QAClC,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,IAAI,QAAQ,CAAC,MAAM;gBAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF"}
|
{"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../src/timeline.ts"],"names":[],"mappings":"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"}
|
2
dist/tsconfig.tsbuildinfo
vendored
2
dist/tsconfig.tsbuildinfo
vendored
File diff suppressed because one or more lines are too long
13
src/net.ts
13
src/net.ts
|
@ -102,8 +102,9 @@ export class Network {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async fetchMessages(opts: { roomId: t.RoomId, dir: "b" | "f", limit?: number, from: string, to?: string }): Promise<t.MessagesResponse> {
|
public async fetchMessages(opts: { roomId: t.RoomId, dir: "b" | "f", limit?: number, from?: string, to?: string }): Promise<t.MessagesResponse> {
|
||||||
let path = `/_matrix/client/v3/rooms/${e(opts.roomId)}/messages?limit=${opts.limit || 50}&from=${e(opts.from)}&dir=${e(opts.dir)}`;
|
let path = `/_matrix/client/v3/rooms/${e(opts.roomId)}/messages?limit=${opts.limit || 50}&dir=${e(opts.dir)}`;
|
||||||
|
if (opts.from) path += `&from=${e(opts.from)}`;
|
||||||
if (opts.to) path += `&to=${e(opts.to)}`;
|
if (opts.to) path += `&to=${e(opts.to)}`;
|
||||||
return this.fetch({ method: "GET", path });
|
return this.fetch({ method: "GET", path });
|
||||||
}
|
}
|
||||||
|
@ -114,7 +115,7 @@ export class Network {
|
||||||
opts: {
|
opts: {
|
||||||
relType?: string,
|
relType?: string,
|
||||||
eventType?: string,
|
eventType?: string,
|
||||||
limit?: string,
|
limit?: number,
|
||||||
dir: "b" | "f",
|
dir: "b" | "f",
|
||||||
from?: string,
|
from?: string,
|
||||||
to?: string,
|
to?: string,
|
||||||
|
@ -129,10 +130,10 @@ export class Network {
|
||||||
return this.fetch({ method: "GET", path });
|
return this.fetch({ method: "GET", path });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async fetchThreads(opts: { from?: string, limit?: number, roomIds?: Array<t.RoomId>, watching: boolean, include: Array<t.IncludeThreads> }): Promise<t.ThreadsResponse> {
|
public async fetchThreads(opts: { from?: string, limit?: number, roomIds?: Array<t.RoomId>, watching?: boolean, include?: Array<t.IncludeThreads> }): Promise<t.ThreadsResponse> {
|
||||||
return this.fetch({
|
return this.fetch({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
path: `/_matrix/client/v1/threads?limit=${opts.limit}${opts.from ? `&from=${e(opts.from)}`: ""}`,
|
path: `/_matrix/client/v1/threads?limit=${opts.limit || 50}${opts.from ? `&from=${e(opts.from)}`: ""}`,
|
||||||
body: {
|
body: {
|
||||||
watching: opts.watching,
|
watching: opts.watching,
|
||||||
room_ids: opts.roomIds,
|
room_ids: opts.roomIds,
|
||||||
|
@ -144,7 +145,7 @@ export class Network {
|
||||||
public async fetchInbox(opts: { roomIds?: Array<t.RoomId>, from?: string, filter?: t.InboxFilter, limit?: number }): Promise<t.InboxResponse> {
|
public async fetchInbox(opts: { roomIds?: Array<t.RoomId>, from?: string, filter?: t.InboxFilter, limit?: number }): Promise<t.InboxResponse> {
|
||||||
return this.fetch({
|
return this.fetch({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
path: `/_matrix/client/v1/inbox?limit=${opts.limit}${opts.from ? `&from=${e(opts.from)}`: ""}`,
|
path: `/_matrix/client/v1/inbox?limit=${opts.limit || 50}${opts.from ? `&from=${e(opts.from)}`: ""}`,
|
||||||
body: {
|
body: {
|
||||||
filter: opts.filter,
|
filter: opts.filter,
|
||||||
room_ids: opts.roomIds,
|
room_ids: opts.roomIds,
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import EventEmitter from "events";
|
import EventEmitter from "events";
|
||||||
import TypedEmitter from "typed-emitter";
|
import TypedEmitter from "typed-emitter";
|
||||||
import { ApiEphemeralEvent, SyncResponseRoom, Unreads } from "./api.js";
|
import { ApiEphemeralEvent, EventId, SyncResponseRoom, Unreads } from "./api.js";
|
||||||
import { Client } from "./client.js";
|
import { Client } from "./client.js";
|
||||||
import { Event, StateEvent } from "./event.js";
|
import { Event, StateEvent } from "./event.js";
|
||||||
import { TimelineSet } from "./timeline.js";
|
import { TimelineSet } from "./timeline.js";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
|
import { Thread } from "./thread.js";
|
||||||
|
|
||||||
type RoomEvents = {
|
type RoomEvents = {
|
||||||
// an event is appended to this room's live timeline
|
// an event is appended to this room's live timeline
|
||||||
|
@ -31,6 +32,8 @@ export class Room extends (EventEmitter as unknown as new () => TypedEmitter<Roo
|
||||||
private state: Map<string, Map<string, StateEvent>> = new Map();
|
private state: Map<string, Map<string, StateEvent>> = new Map();
|
||||||
|
|
||||||
public timelines: TimelineSet;
|
public timelines: TimelineSet;
|
||||||
|
public events: Map<EventId, Event> = new Map();
|
||||||
|
public threads: Map<EventId, Thread> = new Map();
|
||||||
// public members: Members;
|
// public members: Members;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -83,13 +86,13 @@ room.unban(userid)
|
||||||
return [...this.state.get(type)?.values() ?? []];
|
return [...this.state.get(type)?.values() ?? []];
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: return event
|
// TODO: local echo, return event
|
||||||
async sendState(type: string, stateKey: string, content: any) {
|
async sendState(type: string, stateKey: string, content: any) {
|
||||||
// const { event_id } = await this.client.net.sendState(this.id, type, stateKey, content);
|
// const { event_id } = await this.client.net.sendState(this.id, type, stateKey, content);
|
||||||
await this.client.net.sendState(this.id, type, stateKey, content);
|
await this.client.net.sendState(this.id, type, stateKey, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: return event
|
// TODO: local echo(?), return event
|
||||||
async sendEvent(type: string, content: any) {
|
async sendEvent(type: string, content: any) {
|
||||||
await this.client.net.sendEvent(this.id, type, nanoid(), content);
|
await this.client.net.sendEvent(this.id, type, nanoid(), content);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ type ThreadEvents = {
|
||||||
|
|
||||||
export class Thread extends (EventEmitter as unknown as new () => TypedEmitter<ThreadEvents>) {
|
export class Thread extends (EventEmitter as unknown as new () => TypedEmitter<ThreadEvents>) {
|
||||||
public room: Room = this.baseEvent.room;
|
public room: Room = this.baseEvent.room;
|
||||||
|
public timeline: null = null;
|
||||||
|
|
||||||
constructor(public baseEvent: Event) {
|
constructor(public baseEvent: Event) {
|
||||||
super();
|
super();
|
||||||
|
|
|
@ -7,7 +7,12 @@ import { Event } from "./event.js";
|
||||||
import { Thread } from "./thread.js";
|
import { Thread } from "./thread.js";
|
||||||
|
|
||||||
export interface Timeline {
|
export interface Timeline {
|
||||||
|
// if this timeline is actively receiving new events
|
||||||
isLive: boolean,
|
isLive: boolean,
|
||||||
|
|
||||||
|
// isPaginating: boolean,
|
||||||
|
|
||||||
|
// the events in this timeline
|
||||||
events: Array<Event>,
|
events: Array<Event>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,9 +23,7 @@ export class RoomTimeline implements Timeline {
|
||||||
prevBatch: string | null = null;
|
prevBatch: string | null = null;
|
||||||
nextBatch: string | null = null;
|
nextBatch: string | null = null;
|
||||||
|
|
||||||
constructor(public room: Room) {
|
constructor(public room: Room) {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// concat(other: RoomTimeline): RoomTimeline {
|
// concat(other: RoomTimeline): RoomTimeline {
|
||||||
// if (this.events.length === 0) return other;
|
// if (this.events.length === 0) return other;
|
||||||
|
@ -31,7 +34,7 @@ export class RoomTimeline implements Timeline {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ThreadTimeline implements Timeline {
|
export class ThreadTimeline implements Timeline {
|
||||||
public events = [];
|
public events: Array<Event> = [];
|
||||||
public isLive: boolean = false;
|
public isLive: boolean = false;
|
||||||
|
|
||||||
prevBatch: string | null = null;
|
prevBatch: string | null = null;
|
||||||
|
@ -76,14 +79,61 @@ export class TimelineSet {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paginate a timeline for more events
|
// Paginate a timeline for more events
|
||||||
// public paginate(timeline: Timeline, dir: "f" | "b", limit: number = 50) {
|
// TODO: fuse two neighboring timelines together
|
||||||
// throw "todo";
|
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>) {
|
_appendEvents(events: Array<Event>) {
|
||||||
// FIXME: merge timelines together
|
// FIXME: merge timelines together
|
||||||
|
for (const event of events) this.room.events.set(event.id, event);
|
||||||
for (const timeline of this.timelines) {
|
for (const timeline of this.timelines) {
|
||||||
if (timeline.isLive) timeline.events.push(...events);
|
// if (timeline.isLive) timeline.events.push(...events);
|
||||||
|
if (timeline.isLive && timeline instanceof RoomTimeline) timeline.events.push(...events);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue