UNPKG

matrix-js-sdk

Version:
245 lines 11.7 kB
import { type MatrixClient, PendingEventOrdering } from "../client.ts"; import { MatrixEvent } from "./event.ts"; import { EventTimeline } from "./event-timeline.ts"; import { EventTimelineSet, type EventTimelineSetHandlerMap } from "./event-timeline-set.ts"; import { type NotificationCountType, type Room, RoomEvent } from "./room.ts"; import { type RoomState } from "./room-state.ts"; import { ServerControlledNamespacedValue } from "../NamespacedValue.ts"; import { ReadReceipt } from "./read-receipt.ts"; import { type CachedReceiptStructure, type Receipt } from "../@types/read_receipts.ts"; export declare enum ThreadEvent { New = "Thread.new", Update = "Thread.update", NewReply = "Thread.newReply", ViewThread = "Thread.viewThread", Delete = "Thread.delete" } export type ThreadEmittedEvents = Exclude<ThreadEvent, ThreadEvent.New> | RoomEvent.Timeline | RoomEvent.TimelineReset; export type ThreadEventHandlerMap = { [ThreadEvent.Update]: (thread: Thread) => void; [ThreadEvent.NewReply]: (thread: Thread, event: MatrixEvent) => void; [ThreadEvent.ViewThread]: () => void; [ThreadEvent.Delete]: (thread: Thread) => void; } & EventTimelineSetHandlerMap; interface IThreadOpts { room: Room; client: MatrixClient; pendingEventOrdering?: PendingEventOrdering; receipts?: CachedReceiptStructure[]; } export declare enum FeatureSupport { None = 0, Experimental = 1, Stable = 2 } export declare function determineFeatureSupport(stable: boolean, unstable: boolean): FeatureSupport; export declare class Thread extends ReadReceipt<ThreadEmittedEvents, ThreadEventHandlerMap> { readonly id: string; rootEvent: MatrixEvent | undefined; static hasServerSideSupport: FeatureSupport; static hasServerSideListSupport: FeatureSupport; static hasServerSideFwdPaginationSupport: FeatureSupport; /** * A reference to all the events ID at the bottom of the threads */ readonly timelineSet: EventTimelineSet; private _currentUserParticipated; private reEmitter; /** * The last event in this thread, if we don't yet have this in the timeline. * * When we run {@link processRootEvent} (which I think happens during the * setting-up of the thread), we set this to the event pointed to by the * server in `latest_event` [1] that came through with the thread root. * * [1]: https://spec.matrix.org/v1.8/client-server-api/#server-side-aggregation-of-mthread-relationships * * Later, when we have populated the timeline, this is set to undefined, so * that methods like {@link replyToEvent} fall through to use lastReply, * which looks in the timeline for the latest event that is a "thread reply" * i.e. directly refers to the thread root with an m.thread relation. * * So it looks like this is only really relevant when initialEventsFetched * is false, because as soon as the initial events have been fetched, we * should have a proper chunk of timeline from the pagination fetch. * * If all replies in this thread are redacted, this is set to the root * event. I'm not clear what the meaning of this is, since usually after the * initial events have been fetched, lastEvent should be undefined. * In fact, the whole usage inside onRedaction looks suspect - it may be * that we were thinking lastEvent always refers to the actual last event, * but it only does so before initialEventsFetched becomes true. * * The usage of lastEvent inside {@link onEcho} looks suspicious, since I'd * think we probably mean {@link replyToEvent} there - we are trying not to * echo a duplicate event, and we probably want that behaviour even after * initialEventsFetched has become true. * * -- andyb */ private lastEvent; private replyCount; private lastPendingEvent; private pendingReplyCount; readonly room: Room; readonly client: MatrixClient; private readonly pendingEventOrdering; private processRootEventPromise?; /** * Whether or not we need to fetch the initial set of events for the thread. We can * only do this if the server has support for it, so if it doesn't we just pretend * that we've already fetched them. */ initialEventsFetched: boolean; private initalEventFetchProm; /** * An array of events to add to the timeline once the thread has been initialised * with server suppport. */ replayEvents: MatrixEvent[] | null; constructor(id: string, rootEvent: MatrixEvent | undefined, opts: IThreadOpts); private onTimelineReset; private fetchRootEvent; static setServerSideSupport(status: FeatureSupport): void; static setServerSideListSupport(status: FeatureSupport): void; static setServerSideFwdPaginationSupport(status: FeatureSupport): void; private onBeforeRedaction; private onRedaction; private onTimelineEvent; private shouldSendLocalEchoReceipt; private onLocalEcho; private onEcho; get roomState(): RoomState; private addEventToTimeline; /** * TEMPORARY. Only call this when MSC3981 is not available, and we have some * late-arriving events to insert, because we recursively found them as part * of populating a thread. When we have MSC3981 we won't need it, because * they will all be supplied by the homeserver in one request, and they will * already be in the right order in that response. * This is a copy of addEventToTimeline above, modified to call * insertEventIntoTimeline so this event is inserted into our best guess of * the right place based on timestamp. (We should be using Sync Order but we * don't have it.) * * @internal */ insertEventIntoTimeline(event: MatrixEvent): void; addEvents(events: MatrixEvent[], toStartOfTimeline: boolean): void; /** * Add an event to the thread and updates * the tail/root references if needed * Will fire "Thread.update" * @param event - The event to add * @param toStartOfTimeline - whether the event is being added * to the start (and not the end) of the timeline. * @param emit - whether to emit the Update event if the thread was updated or not. */ addEvent(event: MatrixEvent, toStartOfTimeline: boolean, emit?: boolean): void; private addRelatedThreadEvent; processEvent(event: MatrixEvent | null | undefined): Promise<void>; /** * Processes the receipts that were caught during initial sync * When clients become aware of a thread, they try to retrieve those read receipts * and apply them to the current thread * @param receipts - A collection of the receipts cached from initial sync */ private processReceipts; private getRootEventBundledRelationship; private processRootEvent; private updatePendingReplyCount; /** * Reset the live timeline of all timelineSets, and start new ones. * * <p>This is used when /sync returns a 'limited' timeline. 'Limited' means that there's a gap between the messages * /sync returned, and the last known message in our timeline. In such a case, our live timeline isn't live anymore * and has to be replaced by a new one. To make sure we can continue paginating our timelines correctly, we have to * set new pagination tokens on the old and the new timeline. * * @param backPaginationToken - token for back-paginating the new timeline * @param forwardPaginationToken - token for forward-paginating the old live timeline, * if absent or null, all timelines are reset, removing old ones (including the previous live * timeline which would otherwise be unable to paginate forwards without this token). * Removing just the old live timeline whilst preserving previous ones is not supported. */ resetLiveTimeline(backPaginationToken?: string | null, forwardPaginationToken?: string | null): Promise<void>; private updateThreadFromRootEvent; private updateThreadMetadata; private fetchEditsWhereNeeded; setEventMetadata(event: MatrixEvent | null | undefined): void; clearEventMetadata(event: MatrixEvent | null | undefined): void; /** * Finds an event by ID in the current thread */ findEventById(eventId: string): MatrixEvent | undefined; /** * Return last reply to the thread, if known. */ lastReply(matches?: (ev: MatrixEvent) => boolean): MatrixEvent | null; get roomId(): string; /** * The number of messages in the thread * Only count rel_type=m.thread as we want to * exclude annotations from that number */ get length(): number; /** * A getter for the last event of the thread. * This might be a synthesized event, if so, it will not emit any events to listeners. */ get replyToEvent(): MatrixEvent | null; /** * The live event timeline for this thread. * @deprecated Present for backwards compatibility. * Use this.events instead * @returns The live event timeline for this thread. */ get timeline(): MatrixEvent[]; get events(): MatrixEvent[]; has(eventId: string): boolean; get hasCurrentUserParticipated(): boolean; get liveTimeline(): EventTimeline; getUnfilteredTimelineSet(): EventTimelineSet; addReceipt(event: MatrixEvent, synthetic: boolean): void; /** * Get the ID of the event that a given user has read up to within this thread, * or null if we have received no read receipt (at all) from them. * @param userId - The user ID to get read receipt event ID for * @param ignoreSynthesized - If true, return only receipts that have been * sent by the server, not implicit ones generated * by the JS SDK. * @returns ID of the latest event that the given user has read, or null. */ getEventReadUpTo(userId: string, ignoreSynthesized?: boolean): string | null; /** * Determine if the given user has read a particular event. * * It is invalid to call this method with an event that is not part of this thread. * * This is not a definitive check as it only checks the events that have been * loaded client-side at the time of execution. * @param userId - The user ID to check the read state of. * @param eventId - The event ID to check if the user read. * @returns True if the user has read the event, false otherwise. */ hasUserReadEvent(userId: string, eventId: string): boolean; setUnread(type: NotificationCountType, count: number): void; /** * Returns the most recent unthreaded receipt for a given user * @param userId - the MxID of the User * @returns an unthreaded Receipt. Can be undefined if receipts have been disabled * or a user chooses to use private read receipts (or we have simply not received * a receipt from this user yet). */ getLastUnthreadedReceiptFor(userId: string): Receipt | undefined; } export declare const FILTER_RELATED_BY_SENDERS: ServerControlledNamespacedValue<"related_by_senders", "io.element.relation_senders">; export declare const FILTER_RELATED_BY_REL_TYPES: ServerControlledNamespacedValue<"related_by_rel_types", "io.element.relation_types">; export declare const THREAD_RELATION_TYPE: ServerControlledNamespacedValue<"m.thread", "io.element.thread">; export declare enum ThreadFilterType { "My" = 0, "All" = 1 } export declare function threadFilterTypeToFilter(type: ThreadFilterType | null): "all" | "participated"; export {}; //# sourceMappingURL=thread.d.ts.map