You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-12-04 05:02:41 +03:00
Create threads event timeline set in the room model (#2244)
This commit is contained in:
@@ -35,9 +35,16 @@ import {
|
|||||||
} from "../@types/event";
|
} from "../@types/event";
|
||||||
import { IRoomVersionsCapability, MatrixClient, PendingEventOrdering, RoomVersionStability } from "../client";
|
import { IRoomVersionsCapability, MatrixClient, PendingEventOrdering, RoomVersionStability } from "../client";
|
||||||
import { GuestAccess, HistoryVisibility, JoinRule, ResizeMethod } from "../@types/partials";
|
import { GuestAccess, HistoryVisibility, JoinRule, ResizeMethod } from "../@types/partials";
|
||||||
import { Filter } from "../filter";
|
import { Filter, IFilterDefinition } from "../filter";
|
||||||
import { RoomState } from "./room-state";
|
import { RoomState } from "./room-state";
|
||||||
import { Thread, ThreadEvent, EventHandlerMap as ThreadHandlerMap } from "./thread";
|
import {
|
||||||
|
Thread,
|
||||||
|
ThreadEvent,
|
||||||
|
EventHandlerMap as ThreadHandlerMap,
|
||||||
|
FILTER_RELATED_BY_REL_TYPES, THREAD_RELATION_TYPE,
|
||||||
|
FILTER_RELATED_BY_SENDERS,
|
||||||
|
ThreadFilterType,
|
||||||
|
} from "./thread";
|
||||||
import { Method } from "../http-api";
|
import { Method } from "../http-api";
|
||||||
import { TypedEventEmitter } from "./typed-event-emitter";
|
import { TypedEventEmitter } from "./typed-event-emitter";
|
||||||
|
|
||||||
@@ -191,6 +198,7 @@ export class Room extends TypedEventEmitter<EmittedEvents, RoomEventHandlerMap>
|
|||||||
private receiptCacheByEventId: ReceiptCache = {}; // { event_id: ICachedReceipt[] }
|
private receiptCacheByEventId: ReceiptCache = {}; // { event_id: ICachedReceipt[] }
|
||||||
private notificationCounts: Partial<Record<NotificationCountType, number>> = {};
|
private notificationCounts: Partial<Record<NotificationCountType, number>> = {};
|
||||||
private readonly timelineSets: EventTimelineSet[];
|
private readonly timelineSets: EventTimelineSet[];
|
||||||
|
public readonly threadsTimelineSets: EventTimelineSet[] = [];
|
||||||
// any filtered timeline sets we're maintaining for this room
|
// any filtered timeline sets we're maintaining for this room
|
||||||
private readonly filteredTimelineSets: Record<string, EventTimelineSet> = {}; // filter_id: timelineSet
|
private readonly filteredTimelineSets: Record<string, EventTimelineSet> = {}; // filter_id: timelineSet
|
||||||
private readonly pendingEventList?: MatrixEvent[];
|
private readonly pendingEventList?: MatrixEvent[];
|
||||||
@@ -338,6 +346,15 @@ export class Room extends TypedEventEmitter<EmittedEvents, RoomEventHandlerMap>
|
|||||||
RoomEvent.TimelineReset,
|
RoomEvent.TimelineReset,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (this.client?.supportsExperimentalThreads) {
|
||||||
|
Promise.all([
|
||||||
|
this.createThreadTimelineSet(),
|
||||||
|
this.createThreadTimelineSet(ThreadFilterType.My),
|
||||||
|
]).then((timelineSets) => {
|
||||||
|
this.threadsTimelineSets.push(...timelineSets);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.fixUpLegacyTimelineFields();
|
this.fixUpLegacyTimelineFields();
|
||||||
|
|
||||||
if (this.opts.pendingEventOrdering === PendingEventOrdering.Detached) {
|
if (this.opts.pendingEventOrdering === PendingEventOrdering.Detached) {
|
||||||
@@ -1377,6 +1394,61 @@ export class Room extends TypedEventEmitter<EmittedEvents, RoomEventHandlerMap>
|
|||||||
return timelineSet;
|
return timelineSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async createThreadTimelineSet(filterType?: ThreadFilterType): Promise<EventTimelineSet> {
|
||||||
|
let timelineSet: EventTimelineSet;
|
||||||
|
if (Thread.hasServerSideSupport) {
|
||||||
|
const myUserId = this.client.getUserId();
|
||||||
|
const filter = new Filter(myUserId);
|
||||||
|
|
||||||
|
const definition: IFilterDefinition = {
|
||||||
|
"room": {
|
||||||
|
"timeline": {
|
||||||
|
[FILTER_RELATED_BY_REL_TYPES.name]: [THREAD_RELATION_TYPE.name],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (filterType === ThreadFilterType.My) {
|
||||||
|
definition.room.timeline[FILTER_RELATED_BY_SENDERS.name] = [myUserId];
|
||||||
|
}
|
||||||
|
|
||||||
|
filter.setDefinition(definition);
|
||||||
|
const filterId = await this.client.getOrCreateFilter(
|
||||||
|
`THREAD_PANEL_${this.roomId}_${filterType}`,
|
||||||
|
filter,
|
||||||
|
);
|
||||||
|
filter.filterId = filterId;
|
||||||
|
timelineSet = this.getOrCreateFilteredTimelineSet(
|
||||||
|
filter,
|
||||||
|
{
|
||||||
|
prepopulateTimeline: false,
|
||||||
|
pendingEvents: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// An empty pagination token allows to paginate from the very bottom of
|
||||||
|
// the timeline set.
|
||||||
|
timelineSet.getLiveTimeline().setPaginationToken("", EventTimeline.BACKWARDS);
|
||||||
|
} else {
|
||||||
|
timelineSet = new EventTimelineSet(this, {
|
||||||
|
pendingEvents: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
Array.from(this.threads)
|
||||||
|
.forEach(([, thread]) => {
|
||||||
|
if (thread.length === 0) return;
|
||||||
|
const currentUserParticipated = thread.events.some(event => {
|
||||||
|
return event.getSender() === this.client.getUserId();
|
||||||
|
});
|
||||||
|
if (filterType !== ThreadFilterType.My || currentUserParticipated) {
|
||||||
|
timelineSet.getLiveTimeline().addEvent(thread.rootEvent, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return timelineSet;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forget the timelineSet for this room with the given filter
|
* Forget the timelineSet for this room with the given filter
|
||||||
*
|
*
|
||||||
@@ -1476,6 +1548,21 @@ export class Room extends TypedEventEmitter<EmittedEvents, RoomEventHandlerMap>
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.emit(ThreadEvent.New, thread, toStartOfTimeline);
|
this.emit(ThreadEvent.New, thread, toStartOfTimeline);
|
||||||
|
|
||||||
|
this.threadsTimelineSets.forEach(timelineSet => {
|
||||||
|
if (thread.rootEvent) {
|
||||||
|
if (Thread.hasServerSideSupport) {
|
||||||
|
timelineSet.addLiveEvent(thread.rootEvent);
|
||||||
|
} else {
|
||||||
|
timelineSet.addEventToTimeline(
|
||||||
|
thread.rootEvent,
|
||||||
|
timelineSet.getLiveTimeline(),
|
||||||
|
toStartOfTimeline,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -364,3 +364,8 @@ export const THREAD_RELATION_TYPE = new ServerControlledNamespacedValue(
|
|||||||
"m.thread",
|
"m.thread",
|
||||||
"io.element.thread",
|
"io.element.thread",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export enum ThreadFilterType {
|
||||||
|
"My",
|
||||||
|
"All"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user