summaryrefslogtreecommitdiff
path: root/includes/external/matrix/node_modules/matrix-js-sdk/lib/models/thread.js.map
blob: 75f50b552c1519fd3db4bbda1ea06feb32efa5e2 (plain)
1
{"version":3,"file":"thread.js","names":["_client","require","_ReEmitter","_event","_event2","_eventTimeline","_eventTimelineSet","_room","_NamespacedValue","_logger","_readReceipt","_read_receipts","ownKeys","object","enumerableOnly","keys","Object","getOwnPropertySymbols","symbols","filter","sym","getOwnPropertyDescriptor","enumerable","push","apply","_objectSpread","target","i","arguments","length","source","forEach","key","_defineProperty2","default","getOwnPropertyDescriptors","defineProperties","defineProperty","ThreadEvent","exports","FeatureSupport","determineFeatureSupport","stable","unstable","Stable","Experimental","None","Thread","ReadReceipt","constructor","id","rootEvent","opts","_opts$pendingEventOrd","hasServerSideSupport","event","redaction","isRelation","THREAD_RELATION_TYPE","name","room","eventShouldLiveIn","threadId","getId","status","replyCount","updatePendingReplyCount","emit","Update","threadRootId","threadEvent","timeline","clearEventMetadata","lastEvent","_currentUserParticipated","Delete","updateThreadMetadata","toStartOfTimeline","addLocalEchoReceipt","getSender","ReceiptType","Read","onEcho","NewReply","Error","client","pendingEventOrdering","PendingEventOrdering","Chronological","timelineSet","EventTimelineSet","timelineSupport","pendingEvents","reEmitter","TypedReEmitter","reEmit","RoomEvent","Timeline","TimelineReset","on","MatrixEventEvent","BeforeRedaction","onBeforeRedaction","Redaction","onRedaction","LocalEchoUpdated","onLocalEcho","onTimelineEvent","processReceipts","receipts","setEventMetadata","fetchRootEvent","findEventById","eventData","fetchRoomEvent","roomId","mapper","getEventMapper","e","logger","error","processEvent","setServerSideSupport","FILTER_RELATED_BY_SENDERS","setPreferUnstable","FILTER_RELATED_BY_REL_TYPES","setServerSideListSupport","hasServerSideListSupport","setServerSideFwdPaginationSupport","hasServerSideFwdPaginationSupport","roomState","getLiveTimeline","getState","EventTimeline","FORWARDS","addEventToTimeline","liveTimeline","fromCache","events","addEvents","ev","addEvent","lastReply","isNewestReply","localTimestamp","decryptEventIfNeeded","initialEventsFetched","fetchEditsWhereNeeded","RelationType","Annotation","Replace","_this$timelineSet$rel","_this$timelineSet$rel2","_this$replayEvents","replayEvents","relations","aggregateParentEvent","aggregateChildEvent","eventId","receiptType","userId","receipt","synthetic","addReceiptToStructure","getRootEventBundledRelationship","getServerAggregatedRelation","processRootEvent","bundledRelationship","count","current_user_participated","latest_event","room_id","unfilteredPendingEvents","Detached","getPendingEvents","_this$lastEvent","lastPendingEvent","undefined","pendingReplyCount","resetLiveTimeline","backPaginationToken","forwardPaginationToken","oldLive","newLive","newBackward","oldForward","res","createMessagesRequest","Direction","Forward","end","Backward","start","getPaginationToken","_oldForward","setPaginationToken","_newBackward","addEventsToTimeline","paginateEventTimeline","backwards","limit","Math","max","Promise","all","isEncrypted","map","getType","then","makeReplaced","catch","setThread","_event$event","_event$event$unsigned","_event$event$unsigned2","unsigned","matches","replyToEvent","_ref","_this$lastPendingEven","getEvents","has","MatrixEvent","hasCurrentUserParticipated","getUnfilteredTimelineSet","addReceipt","getEventReadUpTo","ignoreSynthesized","isCurrentUser","getUserId","beforeFirstThreadedReceipt","getTs","getOldestThreadedReceiptTs","lastReplyId","readUpToId","unthreadedReceipt","getLastUnthreadedReceiptFor","_this$timeline","_ev$getId","ts","hasUserReadEvent","_this$lastReply$getTs","_this$lastReply","_this$room$getLastUnt","_this$room$getLastUnt2","_this$lastReply$getTs2","_this$lastReply2","unthreadedReceiptTs","beforeLastUnthreadedReceipt","setUnread","type","setThreadUnreadNotificationCount","ServerControlledNamespacedValue","ThreadFilterType","threadFilterTypeToFilter","My"],"sources":["../../src/models/thread.ts"],"sourcesContent":["/*\nCopyright 2021 - 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { Optional } from \"matrix-events-sdk\";\n\nimport { MatrixClient, PendingEventOrdering } from \"../client\";\nimport { TypedReEmitter } from \"../ReEmitter\";\nimport { RelationType } from \"../@types/event\";\nimport { IThreadBundledRelationship, MatrixEvent, MatrixEventEvent } from \"./event\";\nimport { Direction, EventTimeline } from \"./event-timeline\";\nimport { EventTimelineSet, EventTimelineSetHandlerMap } from \"./event-timeline-set\";\nimport { NotificationCountType, Room, RoomEvent } from \"./room\";\nimport { RoomState } from \"./room-state\";\nimport { ServerControlledNamespacedValue } from \"../NamespacedValue\";\nimport { logger } from \"../logger\";\nimport { ReadReceipt } from \"./read-receipt\";\nimport { CachedReceiptStructure, ReceiptType } from \"../@types/read_receipts\";\n\nexport enum ThreadEvent {\n    New = \"Thread.new\",\n    Update = \"Thread.update\",\n    NewReply = \"Thread.newReply\",\n    ViewThread = \"Thread.viewThread\",\n    Delete = \"Thread.delete\",\n}\n\ntype EmittedEvents = Exclude<ThreadEvent, ThreadEvent.New> | RoomEvent.Timeline | RoomEvent.TimelineReset;\n\nexport type EventHandlerMap = {\n    [ThreadEvent.Update]: (thread: Thread) => void;\n    [ThreadEvent.NewReply]: (thread: Thread, event: MatrixEvent) => void;\n    [ThreadEvent.ViewThread]: () => void;\n    [ThreadEvent.Delete]: (thread: Thread) => void;\n} & EventTimelineSetHandlerMap;\n\ninterface IThreadOpts {\n    room: Room;\n    client: MatrixClient;\n    pendingEventOrdering?: PendingEventOrdering;\n    receipts?: CachedReceiptStructure[];\n}\n\nexport enum FeatureSupport {\n    None = 0,\n    Experimental = 1,\n    Stable = 2,\n}\n\nexport function determineFeatureSupport(stable: boolean, unstable: boolean): FeatureSupport {\n    if (stable) {\n        return FeatureSupport.Stable;\n    } else if (unstable) {\n        return FeatureSupport.Experimental;\n    } else {\n        return FeatureSupport.None;\n    }\n}\n\nexport class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {\n    public static hasServerSideSupport = FeatureSupport.None;\n    public static hasServerSideListSupport = FeatureSupport.None;\n    public static hasServerSideFwdPaginationSupport = FeatureSupport.None;\n\n    /**\n     * A reference to all the events ID at the bottom of the threads\n     */\n    public readonly timelineSet: EventTimelineSet;\n    public timeline: MatrixEvent[] = [];\n\n    private _currentUserParticipated = false;\n\n    private reEmitter: TypedReEmitter<EmittedEvents, EventHandlerMap>;\n\n    private lastEvent: MatrixEvent | undefined;\n    private replyCount = 0;\n    private lastPendingEvent: MatrixEvent | undefined;\n    private pendingReplyCount = 0;\n\n    public readonly room: Room;\n    public readonly client: MatrixClient;\n    private readonly pendingEventOrdering: PendingEventOrdering;\n\n    public initialEventsFetched = !Thread.hasServerSideSupport;\n    /**\n     * An array of events to add to the timeline once the thread has been initialised\n     * with server suppport.\n     */\n    public replayEvents: MatrixEvent[] | null = [];\n\n    public constructor(public readonly id: string, public rootEvent: MatrixEvent | undefined, opts: IThreadOpts) {\n        super();\n\n        if (!opts?.room) {\n            // Logging/debugging for https://github.com/vector-im/element-web/issues/22141\n            // Hope is that we end up with a more obvious stack trace.\n            throw new Error(\"element-web#22141: A thread requires a room in order to function\");\n        }\n\n        this.room = opts.room;\n        this.client = opts.client;\n        this.pendingEventOrdering = opts.pendingEventOrdering ?? PendingEventOrdering.Chronological;\n        this.timelineSet = new EventTimelineSet(\n            this.room,\n            {\n                timelineSupport: true,\n                pendingEvents: true,\n            },\n            this.client,\n            this,\n        );\n        this.reEmitter = new TypedReEmitter(this);\n\n        this.reEmitter.reEmit(this.timelineSet, [RoomEvent.Timeline, RoomEvent.TimelineReset]);\n\n        this.room.on(MatrixEventEvent.BeforeRedaction, this.onBeforeRedaction);\n        this.room.on(RoomEvent.Redaction, this.onRedaction);\n        this.room.on(RoomEvent.LocalEchoUpdated, this.onLocalEcho);\n        this.timelineSet.on(RoomEvent.Timeline, this.onTimelineEvent);\n\n        this.processReceipts(opts.receipts);\n\n        // even if this thread is thought to be originating from this client, we initialise it as we may be in a\n        // gappy sync and a thread around this event may already exist.\n        this.updateThreadMetadata();\n        this.setEventMetadata(this.rootEvent);\n    }\n\n    private async fetchRootEvent(): Promise<void> {\n        this.rootEvent = this.room.findEventById(this.id);\n        // If the rootEvent does not exist in the local stores, then fetch it from the server.\n        try {\n            const eventData = await this.client.fetchRoomEvent(this.roomId, this.id);\n            const mapper = this.client.getEventMapper();\n            this.rootEvent = mapper(eventData); // will merge with existing event object if such is known\n        } catch (e) {\n            logger.error(\"Failed to fetch thread root to construct thread with\", e);\n        }\n        await this.processEvent(this.rootEvent);\n    }\n\n    public static setServerSideSupport(status: FeatureSupport): void {\n        Thread.hasServerSideSupport = status;\n        if (status !== FeatureSupport.Stable) {\n            FILTER_RELATED_BY_SENDERS.setPreferUnstable(true);\n            FILTER_RELATED_BY_REL_TYPES.setPreferUnstable(true);\n            THREAD_RELATION_TYPE.setPreferUnstable(true);\n        }\n    }\n\n    public static setServerSideListSupport(status: FeatureSupport): void {\n        Thread.hasServerSideListSupport = status;\n    }\n\n    public static setServerSideFwdPaginationSupport(status: FeatureSupport): void {\n        Thread.hasServerSideFwdPaginationSupport = status;\n    }\n\n    private onBeforeRedaction = (event: MatrixEvent, redaction: MatrixEvent): void => {\n        if (\n            event?.isRelation(THREAD_RELATION_TYPE.name) &&\n            this.room.eventShouldLiveIn(event).threadId === this.id &&\n            event.getId() !== this.id && // the root event isn't counted in the length so ignore this redaction\n            !redaction.status // only respect it when it succeeds\n        ) {\n            this.replyCount--;\n            this.updatePendingReplyCount();\n            this.emit(ThreadEvent.Update, this);\n        }\n    };\n\n    private onRedaction = async (event: MatrixEvent): Promise<void> => {\n        if (event.threadRootId !== this.id) return; // ignore redactions for other timelines\n        if (this.replyCount <= 0) {\n            for (const threadEvent of this.timeline) {\n                this.clearEventMetadata(threadEvent);\n            }\n            this.lastEvent = this.rootEvent;\n            this._currentUserParticipated = false;\n            this.emit(ThreadEvent.Delete, this);\n        } else {\n            await this.updateThreadMetadata();\n        }\n    };\n\n    private onTimelineEvent = (\n        event: MatrixEvent,\n        room: Room | undefined,\n        toStartOfTimeline: boolean | undefined,\n    ): void => {\n        // Add a synthesized receipt when paginating forward in the timeline\n        if (!toStartOfTimeline) {\n            room!.addLocalEchoReceipt(event.getSender()!, event, ReceiptType.Read);\n        }\n        this.onEcho(event, toStartOfTimeline ?? false);\n    };\n\n    private onLocalEcho = (event: MatrixEvent): void => {\n        this.onEcho(event, false);\n    };\n\n    private onEcho = async (event: MatrixEvent, toStartOfTimeline: boolean): Promise<void> => {\n        if (event.threadRootId !== this.id) return; // ignore echoes for other timelines\n        if (this.lastEvent === event) return; // ignore duplicate events\n        await this.updateThreadMetadata();\n        if (!event.isRelation(THREAD_RELATION_TYPE.name)) return; // don't send a new reply event for reactions or edits\n        if (toStartOfTimeline) return; // ignore messages added to the start of the timeline\n        this.emit(ThreadEvent.NewReply, this, event);\n    };\n\n    public get roomState(): RoomState {\n        return this.room.getLiveTimeline().getState(EventTimeline.FORWARDS)!;\n    }\n\n    private addEventToTimeline(event: MatrixEvent, toStartOfTimeline: boolean): void {\n        if (!this.findEventById(event.getId()!)) {\n            this.timelineSet.addEventToTimeline(event, this.liveTimeline, {\n                toStartOfTimeline,\n                fromCache: false,\n                roomState: this.roomState,\n            });\n            this.timeline = this.events;\n        }\n    }\n\n    public addEvents(events: MatrixEvent[], toStartOfTimeline: boolean): void {\n        events.forEach((ev) => this.addEvent(ev, toStartOfTimeline, false));\n        this.updateThreadMetadata();\n    }\n\n    /**\n     * Add an event to the thread and updates\n     * the tail/root references if needed\n     * Will fire \"Thread.update\"\n     * @param event - The event to add\n     * @param toStartOfTimeline - whether the event is being added\n     * to the start (and not the end) of the timeline.\n     * @param emit - whether to emit the Update event if the thread was updated or not.\n     */\n    public async addEvent(event: MatrixEvent, toStartOfTimeline: boolean, emit = true): Promise<void> {\n        this.setEventMetadata(event);\n\n        const lastReply = this.lastReply();\n        const isNewestReply = !lastReply || event.localTimestamp >= lastReply!.localTimestamp;\n\n        // Add all incoming events to the thread's timeline set when there's  no server support\n        if (!Thread.hasServerSideSupport) {\n            // all the relevant membership info to hydrate events with a sender\n            // is held in the main room timeline\n            // We want to fetch the room state from there and pass it down to this thread\n            // timeline set to let it reconcile an event with its relevant RoomMember\n            this.addEventToTimeline(event, toStartOfTimeline);\n\n            this.client.decryptEventIfNeeded(event, {});\n        } else if (!toStartOfTimeline && this.initialEventsFetched && isNewestReply) {\n            this.addEventToTimeline(event, false);\n            this.fetchEditsWhereNeeded(event);\n        } else if (event.isRelation(RelationType.Annotation) || event.isRelation(RelationType.Replace)) {\n            if (!this.initialEventsFetched) {\n                /**\n                 * A thread can be fully discovered via a single sync response\n                 * And when that's the case we still ask the server to do an initialisation\n                 * as it's the safest to ensure we have everything.\n                 * However when we are in that scenario we might loose annotation or edits\n                 *\n                 * This fix keeps a reference to those events and replay them once the thread\n                 * has been initialised properly.\n                 */\n                this.replayEvents?.push(event);\n            } else {\n                this.addEventToTimeline(event, toStartOfTimeline);\n            }\n            // Apply annotations and replace relations to the relations of the timeline only\n            this.timelineSet.relations?.aggregateParentEvent(event);\n            this.timelineSet.relations?.aggregateChildEvent(event, this.timelineSet);\n            return;\n        }\n\n        // If no thread support exists we want to count all thread relation\n        // added as a reply. We can't rely on the bundled relationships count\n        if ((!Thread.hasServerSideSupport || !this.rootEvent) && event.isRelation(THREAD_RELATION_TYPE.name)) {\n            this.replyCount++;\n        }\n\n        if (emit) {\n            this.emit(ThreadEvent.NewReply, this, event);\n            this.updateThreadMetadata();\n        }\n    }\n\n    public async processEvent(event: Optional<MatrixEvent>): Promise<void> {\n        if (event) {\n            this.setEventMetadata(event);\n            await this.fetchEditsWhereNeeded(event);\n        }\n        this.timeline = this.events;\n    }\n\n    /**\n     * Processes the receipts that were caught during initial sync\n     * When clients become aware of a thread, they try to retrieve those read receipts\n     * and apply them to the current thread\n     * @param receipts - A collection of the receipts cached from initial sync\n     */\n    private processReceipts(receipts: CachedReceiptStructure[] = []): void {\n        for (const { eventId, receiptType, userId, receipt, synthetic } of receipts) {\n            this.addReceiptToStructure(eventId, receiptType as ReceiptType, userId, receipt, synthetic);\n        }\n    }\n\n    private getRootEventBundledRelationship(rootEvent = this.rootEvent): IThreadBundledRelationship | undefined {\n        return rootEvent?.getServerAggregatedRelation<IThreadBundledRelationship>(THREAD_RELATION_TYPE.name);\n    }\n\n    private async processRootEvent(): Promise<void> {\n        const bundledRelationship = this.getRootEventBundledRelationship();\n        if (Thread.hasServerSideSupport && bundledRelationship) {\n            this.replyCount = bundledRelationship.count;\n            this._currentUserParticipated = !!bundledRelationship.current_user_participated;\n\n            const mapper = this.client.getEventMapper();\n            // re-insert roomId\n            this.lastEvent = mapper({\n                ...bundledRelationship.latest_event,\n                room_id: this.roomId,\n            });\n            this.updatePendingReplyCount();\n            await this.processEvent(this.lastEvent);\n        }\n    }\n\n    private updatePendingReplyCount(): void {\n        const unfilteredPendingEvents =\n            this.pendingEventOrdering === PendingEventOrdering.Detached ? this.room.getPendingEvents() : this.events;\n        const pendingEvents = unfilteredPendingEvents.filter(\n            (ev) =>\n                ev.threadRootId === this.id &&\n                ev.isRelation(THREAD_RELATION_TYPE.name) &&\n                ev.status !== null &&\n                ev.getId() !== this.lastEvent?.getId(),\n        );\n        this.lastPendingEvent = pendingEvents.length ? pendingEvents[pendingEvents.length - 1] : undefined;\n        this.pendingReplyCount = pendingEvents.length;\n    }\n\n    /**\n     * Reset the live timeline of all timelineSets, and start new ones.\n     *\n     * <p>This is used when /sync returns a 'limited' timeline. 'Limited' means that there's a gap between the messages\n     * /sync returned, and the last known message in our timeline. In such a case, our live timeline isn't live anymore\n     * and has to be replaced by a new one. To make sure we can continue paginating our timelines correctly, we have to\n     * set new pagination tokens on the old and the new timeline.\n     *\n     * @param backPaginationToken -   token for back-paginating the new timeline\n     * @param forwardPaginationToken - token for forward-paginating the old live timeline,\n     * if absent or null, all timelines are reset, removing old ones (including the previous live\n     * timeline which would otherwise be unable to paginate forwards without this token).\n     * Removing just the old live timeline whilst preserving previous ones is not supported.\n     */\n    public async resetLiveTimeline(\n        backPaginationToken?: string | null,\n        forwardPaginationToken?: string | null,\n    ): Promise<void> {\n        const oldLive = this.liveTimeline;\n        this.timelineSet.resetLiveTimeline(backPaginationToken ?? undefined, forwardPaginationToken ?? undefined);\n        const newLive = this.liveTimeline;\n\n        // FIXME: Remove the following as soon as https://github.com/matrix-org/synapse/issues/14830 is resolved.\n        //\n        // The pagination API for thread timelines currently can't handle the type of pagination tokens returned by sync\n        //\n        // To make this work anyway, we'll have to transform them into one of the types that the API can handle.\n        // One option is passing the tokens to /messages, which can handle sync tokens, and returns the right format.\n        // /messages does not return new tokens on requests with a limit of 0.\n        // This means our timelines might overlap a slight bit, but that's not an issue, as we deduplicate messages\n        // anyway.\n\n        let newBackward: string | undefined;\n        let oldForward: string | undefined;\n        if (backPaginationToken) {\n            const res = await this.client.createMessagesRequest(this.roomId, backPaginationToken, 1, Direction.Forward);\n            newBackward = res.end;\n        }\n        if (forwardPaginationToken) {\n            const res = await this.client.createMessagesRequest(\n                this.roomId,\n                forwardPaginationToken,\n                1,\n                Direction.Backward,\n            );\n            oldForward = res.start;\n        }\n        // Only replace the token if we don't have paginated away from this position already. This situation doesn't\n        // occur today, but if the above issue is resolved, we'd have to go down this path.\n        if (forwardPaginationToken && oldLive.getPaginationToken(Direction.Forward) === forwardPaginationToken) {\n            oldLive.setPaginationToken(oldForward ?? null, Direction.Forward);\n        }\n        if (backPaginationToken && newLive.getPaginationToken(Direction.Backward) === backPaginationToken) {\n            newLive.setPaginationToken(newBackward ?? null, Direction.Backward);\n        }\n    }\n\n    private async updateThreadMetadata(): Promise<void> {\n        this.updatePendingReplyCount();\n\n        if (Thread.hasServerSideSupport) {\n            // Ensure we show *something* as soon as possible, we'll update it as soon as we get better data, but we\n            // don't want the thread preview to be empty if we can avoid it\n            if (!this.initialEventsFetched) {\n                await this.processRootEvent();\n            }\n            await this.fetchRootEvent();\n        }\n        await this.processRootEvent();\n\n        if (!this.initialEventsFetched) {\n            this.initialEventsFetched = true;\n            // fetch initial event to allow proper pagination\n            try {\n                // if the thread has regular events, this will just load the last reply.\n                // if the thread is newly created, this will load the root event.\n                if (this.replyCount === 0 && this.rootEvent) {\n                    this.timelineSet.addEventsToTimeline([this.rootEvent], true, this.liveTimeline, null);\n                    this.liveTimeline.setPaginationToken(null, Direction.Backward);\n                } else {\n                    await this.client.paginateEventTimeline(this.liveTimeline, {\n                        backwards: true,\n                        limit: Math.max(1, this.length),\n                    });\n                }\n                for (const event of this.replayEvents!) {\n                    this.addEvent(event, false);\n                }\n                this.replayEvents = null;\n                // just to make sure that, if we've created a timeline window for this thread before the thread itself\n                // existed (e.g. when creating a new thread), we'll make sure the panel is force refreshed correctly.\n                this.emit(RoomEvent.TimelineReset, this.room, this.timelineSet, true);\n            } catch (e) {\n                logger.error(\"Failed to load start of newly created thread: \", e);\n                this.initialEventsFetched = false;\n            }\n        }\n\n        this.emit(ThreadEvent.Update, this);\n    }\n\n    // XXX: Workaround for https://github.com/matrix-org/matrix-spec-proposals/pull/2676/files#r827240084\n    private async fetchEditsWhereNeeded(...events: MatrixEvent[]): Promise<unknown> {\n        return Promise.all(\n            events\n                .filter((e) => e.isEncrypted())\n                .map((event: MatrixEvent) => {\n                    if (event.isRelation()) return; // skip - relations don't get edits\n                    return this.client\n                        .relations(this.roomId, event.getId()!, RelationType.Replace, event.getType(), {\n                            limit: 1,\n                        })\n                        .then((relations) => {\n                            if (relations.events.length) {\n                                event.makeReplaced(relations.events[0]);\n                            }\n                        })\n                        .catch((e) => {\n                            logger.error(\"Failed to load edits for encrypted thread event\", e);\n                        });\n                }),\n        );\n    }\n\n    public setEventMetadata(event: Optional<MatrixEvent>): void {\n        if (event) {\n            EventTimeline.setEventMetadata(event, this.roomState, false);\n            event.setThread(this);\n        }\n    }\n\n    public clearEventMetadata(event: Optional<MatrixEvent>): void {\n        if (event) {\n            event.setThread(undefined);\n            delete event.event?.unsigned?.[\"m.relations\"]?.[THREAD_RELATION_TYPE.name];\n        }\n    }\n\n    /**\n     * Finds an event by ID in the current thread\n     */\n    public findEventById(eventId: string): MatrixEvent | undefined {\n        return this.timelineSet.findEventById(eventId);\n    }\n\n    /**\n     * Return last reply to the thread, if known.\n     */\n    public lastReply(matches: (ev: MatrixEvent) => boolean = (): boolean => true): MatrixEvent | null {\n        for (let i = this.timeline.length - 1; i >= 0; i--) {\n            const event = this.timeline[i];\n            if (matches(event)) {\n                return event;\n            }\n        }\n        return null;\n    }\n\n    public get roomId(): string {\n        return this.room.roomId;\n    }\n\n    /**\n     * The number of messages in the thread\n     * Only count rel_type=m.thread as we want to\n     * exclude annotations from that number\n     */\n    public get length(): number {\n        return this.replyCount + this.pendingReplyCount;\n    }\n\n    /**\n     * A getter for the last event of the thread.\n     * This might be a synthesized event, if so, it will not emit any events to listeners.\n     */\n    public get replyToEvent(): Optional<MatrixEvent> {\n        return this.lastPendingEvent ?? this.lastEvent ?? this.lastReply();\n    }\n\n    public get events(): MatrixEvent[] {\n        return this.liveTimeline.getEvents();\n    }\n\n    public has(eventId: string): boolean {\n        return this.timelineSet.findEventById(eventId) instanceof MatrixEvent;\n    }\n\n    public get hasCurrentUserParticipated(): boolean {\n        return this._currentUserParticipated;\n    }\n\n    public get liveTimeline(): EventTimeline {\n        return this.timelineSet.getLiveTimeline();\n    }\n\n    public getUnfilteredTimelineSet(): EventTimelineSet {\n        return this.timelineSet;\n    }\n\n    public addReceipt(event: MatrixEvent, synthetic: boolean): void {\n        throw new Error(\"Unsupported function on the thread model\");\n    }\n\n    /**\n     * Get the ID of the event that a given user has read up to within this thread,\n     * or null if we have received no read receipt (at all) from them.\n     * @param userId - The user ID to get read receipt event ID for\n     * @param ignoreSynthesized - If true, return only receipts that have been\n     *                            sent by the server, not implicit ones generated\n     *                            by the JS SDK.\n     * @returns ID of the latest event that the given user has read, or null.\n     */\n    public getEventReadUpTo(userId: string, ignoreSynthesized?: boolean): string | null {\n        const isCurrentUser = userId === this.client.getUserId();\n        const lastReply = this.timeline[this.timeline.length - 1];\n        if (isCurrentUser && lastReply) {\n            // If the last activity in a thread is prior to the first threaded read receipt\n            // sent in the room (suggesting that it was sent before the user started\n            // using a client that supported threaded read receipts), we want to\n            // consider this thread as read.\n            const beforeFirstThreadedReceipt = lastReply.getTs() < this.room.getOldestThreadedReceiptTs();\n            const lastReplyId = lastReply.getId();\n            // Some unsent events do not have an ID, we do not want to consider them read\n            if (beforeFirstThreadedReceipt && lastReplyId) {\n                return lastReplyId;\n            }\n        }\n\n        const readUpToId = super.getEventReadUpTo(userId, ignoreSynthesized);\n\n        // Check whether the unthreaded read receipt for that user is more recent\n        // than the read receipt inside that thread.\n        if (lastReply) {\n            const unthreadedReceipt = this.room.getLastUnthreadedReceiptFor(userId);\n            if (!unthreadedReceipt) {\n                return readUpToId;\n            }\n\n            for (let i = this.timeline?.length - 1; i >= 0; --i) {\n                const ev = this.timeline[i];\n                // If we encounter the `readUpToId` we do not need to look further\n                // there is no \"more recent\" unthreaded read receipt\n                if (ev.getId() === readUpToId) return readUpToId;\n\n                // Inspecting events from most recent to oldest, we're checking\n                // whether an unthreaded read receipt is more recent that the current event.\n                // We usually prefer relying on the order of the DAG but in this scenario\n                // it is not possible and we have to rely on timestamp\n                if (ev.getTs() < unthreadedReceipt.ts) return ev.getId() ?? readUpToId;\n            }\n        }\n\n        return readUpToId;\n    }\n\n    /**\n     * Determine if the given user has read a particular event.\n     *\n     * It is invalid to call this method with an event that is not part of this thread.\n     *\n     * This is not a definitive check as it only checks the events that have been\n     * loaded client-side at the time of execution.\n     * @param userId - The user ID to check the read state of.\n     * @param eventId - The event ID to check if the user read.\n     * @returns True if the user has read the event, false otherwise.\n     */\n    public hasUserReadEvent(userId: string, eventId: string): boolean {\n        if (userId === this.client.getUserId()) {\n            // Consider an event read if it's part of a thread that is before the\n            // first threaded receipt sent in that room. It is likely that it is\n            // part of a thread that was created before MSC3771 was implemented.\n            // Or before the last unthreaded receipt for the logged in user\n            const beforeFirstThreadedReceipt =\n                (this.lastReply()?.getTs() ?? 0) < this.room.getOldestThreadedReceiptTs();\n            const unthreadedReceiptTs = this.room.getLastUnthreadedReceiptFor(userId)?.ts ?? 0;\n            const beforeLastUnthreadedReceipt = (this?.lastReply()?.getTs() ?? 0) < unthreadedReceiptTs;\n            if (beforeFirstThreadedReceipt || beforeLastUnthreadedReceipt) {\n                return true;\n            }\n        }\n\n        return super.hasUserReadEvent(userId, eventId);\n    }\n\n    public setUnread(type: NotificationCountType, count: number): void {\n        return this.room.setThreadUnreadNotificationCount(this.id, type, count);\n    }\n}\n\nexport const FILTER_RELATED_BY_SENDERS = new ServerControlledNamespacedValue(\n    \"related_by_senders\",\n    \"io.element.relation_senders\",\n);\nexport const FILTER_RELATED_BY_REL_TYPES = new ServerControlledNamespacedValue(\n    \"related_by_rel_types\",\n    \"io.element.relation_types\",\n);\nexport const THREAD_RELATION_TYPE = new ServerControlledNamespacedValue(\"m.thread\", \"io.element.thread\");\n\nexport enum ThreadFilterType {\n    \"My\",\n    \"All\",\n}\n\nexport function threadFilterTypeToFilter(type: ThreadFilterType | null): \"all\" | \"participated\" {\n    switch (type) {\n        case ThreadFilterType.My:\n            return \"participated\";\n        default:\n            return \"all\";\n    }\n}\n"],"mappings":"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"}