Apply more strict typescript around the codebase (#2778)
* Apply more strict typescript around the codebase * Fix tests * Revert strict mode commit * Iterate strict * Iterate * Iterate strict * Iterate * Fix tests * Iterate * Iterate strict * Add tests * Iterate * Iterate * Fix tests * Fix tests * Strict types be strict * Fix types * detectOpenHandles * Strict * Fix client not stopping * Add sync peeking tests * Make test happier * More strict * Iterate * Stabilise * Moar strictness * Improve coverage * Fix types * Fix types * Improve types further * Fix types * Improve typing of NamespacedValue * Fix types
This commit is contained in:
committed by
GitHub
parent
fdbbd9bca4
commit
867a0ca7ee
@@ -86,7 +86,7 @@ export class MSC3089TreeSpace {
|
||||
public readonly room: Room;
|
||||
|
||||
public constructor(private client: MatrixClient, public readonly roomId: string) {
|
||||
this.room = this.client.getRoom(this.roomId);
|
||||
this.room = this.client.getRoom(this.roomId)!;
|
||||
|
||||
if (!this.room) throw new Error("Unknown room");
|
||||
}
|
||||
@@ -282,7 +282,7 @@ export class MSC3089TreeSpace {
|
||||
const members = this.room.currentState.getStateEvents(EventType.RoomMember);
|
||||
for (const member of members) {
|
||||
const isNotUs = member.getStateKey() !== this.client.getUserId();
|
||||
if (isNotUs && kickMemberships.includes(member.getContent().membership)) {
|
||||
if (isNotUs && kickMemberships.includes(member.getContent().membership!)) {
|
||||
const stateKey = member.getStateKey();
|
||||
if (!stateKey) {
|
||||
throw new Error("State key not found for branch");
|
||||
|
||||
+21
-19
@@ -51,21 +51,21 @@ export const getBeaconInfoIdentifier = (event: MatrixEvent): BeaconIdentifier =>
|
||||
// https://github.com/matrix-org/matrix-spec-proposals/pull/3672
|
||||
export class Beacon extends TypedEventEmitter<Exclude<BeaconEvent, BeaconEvent.New>, BeaconEventHandlerMap> {
|
||||
public readonly roomId: string;
|
||||
private _beaconInfo: BeaconInfoState;
|
||||
private _isLive: boolean;
|
||||
private livenessWatchTimeout: ReturnType<typeof setTimeout>;
|
||||
private _latestLocationEvent: MatrixEvent | undefined;
|
||||
private _beaconInfo?: BeaconInfoState;
|
||||
private _isLive?: boolean;
|
||||
private livenessWatchTimeout?: ReturnType<typeof setTimeout>;
|
||||
private _latestLocationEvent?: MatrixEvent;
|
||||
|
||||
constructor(
|
||||
private rootEvent: MatrixEvent,
|
||||
) {
|
||||
super();
|
||||
this.setBeaconInfo(this.rootEvent);
|
||||
this.roomId = this.rootEvent.getRoomId();
|
||||
this.roomId = this.rootEvent.getRoomId()!;
|
||||
}
|
||||
|
||||
public get isLive(): boolean {
|
||||
return this._isLive;
|
||||
return !!this._isLive;
|
||||
}
|
||||
|
||||
public get identifier(): BeaconIdentifier {
|
||||
@@ -77,14 +77,14 @@ export class Beacon extends TypedEventEmitter<Exclude<BeaconEvent, BeaconEvent.N
|
||||
}
|
||||
|
||||
public get beaconInfoOwner(): string {
|
||||
return this.rootEvent.getStateKey();
|
||||
return this.rootEvent.getStateKey()!;
|
||||
}
|
||||
|
||||
public get beaconInfoEventType(): string {
|
||||
return this.rootEvent.getType();
|
||||
}
|
||||
|
||||
public get beaconInfo(): BeaconInfoState {
|
||||
public get beaconInfo(): BeaconInfoState | undefined {
|
||||
return this._beaconInfo;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ export class Beacon extends TypedEventEmitter<Exclude<BeaconEvent, BeaconEvent.N
|
||||
throw new Error('Invalid updating event');
|
||||
}
|
||||
// don't update beacon with an older event
|
||||
if (beaconInfoEvent.event.origin_server_ts < this.rootEvent.event.origin_server_ts) {
|
||||
if (beaconInfoEvent.getTs() < this.rootEvent.getTs()) {
|
||||
return;
|
||||
}
|
||||
this.rootEvent = beaconInfoEvent;
|
||||
@@ -130,20 +130,21 @@ export class Beacon extends TypedEventEmitter<Exclude<BeaconEvent, BeaconEvent.N
|
||||
}
|
||||
|
||||
this.checkLiveness();
|
||||
if (!this.beaconInfo) return;
|
||||
if (this.isLive) {
|
||||
const expiryInMs = (this._beaconInfo?.timestamp + this._beaconInfo?.timeout) - Date.now();
|
||||
const expiryInMs = (this.beaconInfo.timestamp + this.beaconInfo.timeout) - Date.now();
|
||||
if (expiryInMs > 1) {
|
||||
this.livenessWatchTimeout = setTimeout(
|
||||
() => { this.monitorLiveness(); },
|
||||
expiryInMs,
|
||||
);
|
||||
}
|
||||
} else if (this._beaconInfo?.timestamp > Date.now()) {
|
||||
} else if (this.beaconInfo.timestamp > Date.now()) {
|
||||
// beacon start timestamp is in the future
|
||||
// check liveness again then
|
||||
this.livenessWatchTimeout = setTimeout(
|
||||
() => { this.monitorLiveness(); },
|
||||
this.beaconInfo?.timestamp - Date.now(),
|
||||
this.beaconInfo.timestamp - Date.now(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -165,22 +166,22 @@ export class Beacon extends TypedEventEmitter<Exclude<BeaconEvent, BeaconEvent.N
|
||||
const { timestamp } = parsed;
|
||||
return (
|
||||
// only include positions that were taken inside the beacon's live period
|
||||
isTimestampInDuration(this._beaconInfo.timestamp, this._beaconInfo.timeout, timestamp) &&
|
||||
isTimestampInDuration(this._beaconInfo!.timestamp, this._beaconInfo!.timeout, timestamp) &&
|
||||
// ignore positions older than our current latest location
|
||||
(!this.latestLocationState || timestamp > this.latestLocationState.timestamp)
|
||||
(!this.latestLocationState || timestamp > this.latestLocationState.timestamp!)
|
||||
);
|
||||
});
|
||||
const latestLocationEvent = validLocationEvents.sort(sortEventsByLatestContentTimestamp)?.[0];
|
||||
|
||||
if (latestLocationEvent) {
|
||||
this._latestLocationEvent = latestLocationEvent;
|
||||
this.emit(BeaconEvent.LocationUpdate, this.latestLocationState);
|
||||
this.emit(BeaconEvent.LocationUpdate, this.latestLocationState!);
|
||||
}
|
||||
}
|
||||
|
||||
private clearLatestLocation = () => {
|
||||
this._latestLocationEvent = undefined;
|
||||
this.emit(BeaconEvent.LocationUpdate, this.latestLocationState);
|
||||
this.emit(BeaconEvent.LocationUpdate, this.latestLocationState!);
|
||||
};
|
||||
|
||||
private setBeaconInfo(event: MatrixEvent): void {
|
||||
@@ -195,9 +196,10 @@ export class Beacon extends TypedEventEmitter<Exclude<BeaconEvent, BeaconEvent.N
|
||||
// when Alice's system clock deviates slightly from Bob's a beacon Alice intended to be live
|
||||
// may have a start timestamp in the future from Bob's POV
|
||||
// handle this by adding 6min of leniency to the start timestamp when it is in the future
|
||||
const startTimestamp = this._beaconInfo?.timestamp > Date.now() ?
|
||||
this._beaconInfo?.timestamp - 360000 /* 6min */ :
|
||||
this._beaconInfo?.timestamp;
|
||||
if (!this.beaconInfo) return;
|
||||
const startTimestamp = this.beaconInfo.timestamp > Date.now() ?
|
||||
this.beaconInfo.timestamp - 360000 /* 6min */ :
|
||||
this.beaconInfo.timestamp;
|
||||
this._isLive = !!this._beaconInfo?.live &&
|
||||
isTimestampInDuration(startTimestamp, this._beaconInfo?.timeout, Date.now());
|
||||
|
||||
|
||||
@@ -822,7 +822,7 @@ export class EventTimelineSet extends TypedEventEmitter<EmittedEvents, EventTime
|
||||
// linkedlist to see which comes first.
|
||||
|
||||
// first work forwards from timeline1
|
||||
let tl = timeline1;
|
||||
let tl: EventTimeline | null = timeline1;
|
||||
while (tl) {
|
||||
if (tl === timeline2) {
|
||||
// timeline1 is before timeline2
|
||||
|
||||
@@ -77,7 +77,7 @@ export class EventTimeline {
|
||||
event.sender = stateContext.getSentinelMember(event.getSender());
|
||||
}
|
||||
if (!event.target?.events?.member && event.getType() === EventType.RoomMember) {
|
||||
event.target = stateContext.getSentinelMember(event.getStateKey());
|
||||
event.target = stateContext.getSentinelMember(event.getStateKey()!);
|
||||
}
|
||||
|
||||
if (event.isState()) {
|
||||
@@ -97,8 +97,8 @@ export class EventTimeline {
|
||||
private baseIndex = 0;
|
||||
private startState: RoomState;
|
||||
private endState: RoomState;
|
||||
private prevTimeline?: EventTimeline;
|
||||
private nextTimeline?: EventTimeline;
|
||||
private prevTimeline: EventTimeline | null = null;
|
||||
private nextTimeline: EventTimeline | null = null;
|
||||
public paginationRequests: Record<Direction, Promise<boolean> | null> = {
|
||||
[Direction.Backward]: null,
|
||||
[Direction.Forward]: null,
|
||||
@@ -131,9 +131,6 @@ export class EventTimeline {
|
||||
this.endState = new RoomState(this.roomId);
|
||||
this.endState.paginationToken = null;
|
||||
|
||||
this.prevTimeline = null;
|
||||
this.nextTimeline = null;
|
||||
|
||||
// this is used by client.js
|
||||
this.paginationRequests = { 'b': null, 'f': null };
|
||||
|
||||
@@ -226,7 +223,7 @@ export class EventTimeline {
|
||||
* Get the ID of the room for this timeline
|
||||
* @return {string} room ID
|
||||
*/
|
||||
public getRoomId(): string {
|
||||
public getRoomId(): string | null {
|
||||
return this.roomId;
|
||||
}
|
||||
|
||||
@@ -234,7 +231,7 @@ export class EventTimeline {
|
||||
* Get the filter for this timeline's timelineSet (if any)
|
||||
* @return {Filter} filter
|
||||
*/
|
||||
public getFilter(): Filter {
|
||||
public getFilter(): Filter | undefined {
|
||||
return this.eventTimelineSet.getFilter();
|
||||
}
|
||||
|
||||
@@ -324,7 +321,7 @@ export class EventTimeline {
|
||||
* @return {?EventTimeline} previous or following timeline, if they have been
|
||||
* joined up.
|
||||
*/
|
||||
public getNeighbouringTimeline(direction: Direction): EventTimeline {
|
||||
public getNeighbouringTimeline(direction: Direction): EventTimeline | null {
|
||||
if (direction == EventTimeline.BACKWARDS) {
|
||||
return this.prevTimeline;
|
||||
} else if (direction == EventTimeline.FORWARDS) {
|
||||
@@ -391,7 +388,7 @@ export class EventTimeline {
|
||||
roomState?: RoomState,
|
||||
): void {
|
||||
let toStartOfTimeline = !!toStartOfTimelineOrOpts;
|
||||
let timelineWasEmpty: boolean;
|
||||
let timelineWasEmpty: boolean | undefined;
|
||||
if (typeof (toStartOfTimelineOrOpts) === 'object') {
|
||||
({ toStartOfTimeline, roomState, timelineWasEmpty } = toStartOfTimelineOrOpts);
|
||||
} else if (toStartOfTimelineOrOpts !== undefined) {
|
||||
|
||||
+8
-11
@@ -34,6 +34,7 @@ import { TypedReEmitter } from '../ReEmitter';
|
||||
import { MatrixError } from "../http-api";
|
||||
import { TypedEventEmitter } from "./typed-event-emitter";
|
||||
import { EventStatus } from "./event-status";
|
||||
import { DecryptionError } from "../crypto/algorithms";
|
||||
|
||||
export { EventStatus } from "./event-status";
|
||||
|
||||
@@ -685,14 +686,6 @@ export class MatrixEvent extends TypedEventEmitter<MatrixEventEmittedEvents, Mat
|
||||
* attempt is completed.
|
||||
*/
|
||||
public async attemptDecryption(crypto: Crypto, options: IDecryptOptions = {}): Promise<void> {
|
||||
// For backwards compatibility purposes
|
||||
// The function signature used to be attemptDecryption(crypto, isRetry)
|
||||
if (typeof options === "boolean") {
|
||||
options = {
|
||||
isRetry: options,
|
||||
};
|
||||
}
|
||||
|
||||
// start with a couple of sanity checks.
|
||||
if (!this.isEncrypted()) {
|
||||
throw new Error("Attempt to decrypt event which isn't encrypted");
|
||||
@@ -822,15 +815,19 @@ export class MatrixEvent extends TypedEventEmitter<MatrixEventEmittedEvents, Mat
|
||||
//
|
||||
if (this.retryDecryption) {
|
||||
// decryption error, but we have a retry queued.
|
||||
logger.log(`Got error decrypting event (id=${this.getId()}: ${e.detailedString}), but retrying`, e);
|
||||
logger.log(`Got error decrypting event (id=${this.getId()}: ` +
|
||||
`${(<DecryptionError>e).detailedString}), but retrying`, e);
|
||||
continue;
|
||||
}
|
||||
|
||||
// decryption error, no retries queued. Warn about the error and
|
||||
// set it to m.bad.encrypted.
|
||||
logger.warn(`Got error decrypting event (id=${this.getId()}: ${e.detailedString})`, e);
|
||||
logger.warn(
|
||||
`Got error decrypting event (id=${this.getId()}: ${(<DecryptionError>e).detailedString})`,
|
||||
e,
|
||||
);
|
||||
|
||||
res = this.badEncryptedMessage(e.message);
|
||||
res = this.badEncryptedMessage((<DecryptionError>e).message);
|
||||
}
|
||||
|
||||
// at this point, we've either successfully decrypted the event, or have given up
|
||||
|
||||
@@ -118,31 +118,31 @@ export class RelationsContainer {
|
||||
const { event_id: relatesToEventId, rel_type: relationType } = relation;
|
||||
const eventType = event.getType();
|
||||
|
||||
let relationsForEvent = this.relations.get(relatesToEventId);
|
||||
let relationsForEvent = this.relations.get(relatesToEventId!);
|
||||
if (!relationsForEvent) {
|
||||
relationsForEvent = new Map<RelationType | string, Map<EventType | string, Relations>>();
|
||||
this.relations.set(relatesToEventId, relationsForEvent);
|
||||
this.relations.set(relatesToEventId!, relationsForEvent);
|
||||
}
|
||||
|
||||
let relationsWithRelType = relationsForEvent.get(relationType);
|
||||
let relationsWithRelType = relationsForEvent.get(relationType!);
|
||||
if (!relationsWithRelType) {
|
||||
relationsWithRelType = new Map<EventType | string, Relations>();
|
||||
relationsForEvent.set(relationType, relationsWithRelType);
|
||||
relationsForEvent.set(relationType!, relationsWithRelType);
|
||||
}
|
||||
|
||||
let relationsWithEventType = relationsWithRelType.get(eventType);
|
||||
if (!relationsWithEventType) {
|
||||
relationsWithEventType = new Relations(
|
||||
relationType,
|
||||
relationType!,
|
||||
eventType,
|
||||
this.client,
|
||||
);
|
||||
relationsWithRelType.set(eventType, relationsWithEventType);
|
||||
|
||||
const room = this.room ?? timelineSet?.room;
|
||||
const relatesToEvent = timelineSet?.findEventById(relatesToEventId)
|
||||
?? room?.findEventById(relatesToEventId)
|
||||
?? room?.getPendingEvent(relatesToEventId);
|
||||
const relatesToEvent = timelineSet?.findEventById(relatesToEventId!)
|
||||
?? room?.findEventById(relatesToEventId!)
|
||||
?? room?.getPendingEvent(relatesToEventId!);
|
||||
if (relatesToEvent) {
|
||||
relationsWithEventType.setTargetEvent(relatesToEvent);
|
||||
}
|
||||
|
||||
+14
-18
@@ -47,7 +47,7 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
||||
private annotationsByKey: Record<string, Set<MatrixEvent>> = {};
|
||||
private annotationsBySender: Record<string, Set<MatrixEvent>> = {};
|
||||
private sortedAnnotationsByKey: [string, Set<MatrixEvent>][] = [];
|
||||
private targetEvent: MatrixEvent = null;
|
||||
private targetEvent: MatrixEvent | null = null;
|
||||
private creationEmitted = false;
|
||||
private readonly client: MatrixClient;
|
||||
|
||||
@@ -107,7 +107,7 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
||||
this.addAnnotationToAggregation(event);
|
||||
} else if (this.relationType === RelationType.Replace && this.targetEvent && !this.targetEvent.isState()) {
|
||||
const lastReplacement = await this.getLastReplacement();
|
||||
this.targetEvent.makeReplaced(lastReplacement);
|
||||
this.targetEvent.makeReplaced(lastReplacement!);
|
||||
}
|
||||
|
||||
event.on(MatrixEventEvent.BeforeRedaction, this.onBeforeRedaction);
|
||||
@@ -148,7 +148,7 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
||||
this.removeAnnotationFromAggregation(event);
|
||||
} else if (this.relationType === RelationType.Replace && this.targetEvent && !this.targetEvent.isState()) {
|
||||
const lastReplacement = await this.getLastReplacement();
|
||||
this.targetEvent.makeReplaced(lastReplacement);
|
||||
this.targetEvent.makeReplaced(lastReplacement!);
|
||||
}
|
||||
|
||||
this.emit(RelationsEvent.Remove, event);
|
||||
@@ -189,10 +189,8 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
||||
}
|
||||
|
||||
private addAnnotationToAggregation(event: MatrixEvent): void {
|
||||
const { key } = event.getRelation();
|
||||
if (!key) {
|
||||
return;
|
||||
}
|
||||
const { key } = event.getRelation() ?? {};
|
||||
if (!key) return;
|
||||
|
||||
let eventsForKey = this.annotationsByKey[key];
|
||||
if (!eventsForKey) {
|
||||
@@ -218,10 +216,8 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
||||
}
|
||||
|
||||
private removeAnnotationFromAggregation(event: MatrixEvent): void {
|
||||
const { key } = event.getRelation();
|
||||
if (!key) {
|
||||
return;
|
||||
}
|
||||
const { key } = event.getRelation() ?? {};
|
||||
if (!key) return;
|
||||
|
||||
const eventsForKey = this.annotationsByKey[key];
|
||||
if (eventsForKey) {
|
||||
@@ -265,7 +261,7 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
||||
this.removeAnnotationFromAggregation(redactedEvent);
|
||||
} else if (this.relationType === RelationType.Replace && this.targetEvent && !this.targetEvent.isState()) {
|
||||
const lastReplacement = await this.getLastReplacement();
|
||||
this.targetEvent.makeReplaced(lastReplacement);
|
||||
this.targetEvent.makeReplaced(lastReplacement!);
|
||||
}
|
||||
|
||||
redactedEvent.removeListener(MatrixEventEvent.BeforeRedaction, this.onBeforeRedaction);
|
||||
@@ -283,7 +279,7 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
||||
* An array of [key, events] pairs sorted by descending event count.
|
||||
* The events are stored in a Set (which preserves insertion order).
|
||||
*/
|
||||
public getSortedAnnotationsByKey() {
|
||||
public getSortedAnnotationsByKey(): [string, Set<MatrixEvent>][] | null {
|
||||
if (this.relationType !== RelationType.Annotation) {
|
||||
// Other relation types are not grouped currently.
|
||||
return null;
|
||||
@@ -301,7 +297,7 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
||||
* An object with each relation sender as a key and the matching Set of
|
||||
* events for that sender as a value.
|
||||
*/
|
||||
public getAnnotationsBySender() {
|
||||
public getAnnotationsBySender(): Record<string, Set<MatrixEvent>> | null {
|
||||
if (this.relationType !== RelationType.Annotation) {
|
||||
// Other relation types are not grouped currently.
|
||||
return null;
|
||||
@@ -335,8 +331,8 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
||||
const replaceRelation = this.targetEvent.getServerAggregatedRelation<IAggregatedRelation>(RelationType.Replace);
|
||||
const minTs = replaceRelation?.origin_server_ts;
|
||||
|
||||
const lastReplacement = this.getRelations().reduce((last, event) => {
|
||||
if (event.getSender() !== this.targetEvent.getSender()) {
|
||||
const lastReplacement = this.getRelations().reduce<MatrixEvent | null>((last, event) => {
|
||||
if (event.getSender() !== this.targetEvent!.getSender()) {
|
||||
return last;
|
||||
}
|
||||
if (minTs && minTs > event.getTs()) {
|
||||
@@ -348,8 +344,8 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
||||
return event;
|
||||
}, null);
|
||||
|
||||
if (lastReplacement?.shouldAttemptDecryption()) {
|
||||
await lastReplacement.attemptDecryption(this.client.crypto);
|
||||
if (lastReplacement?.shouldAttemptDecryption() && this.client.isCryptoEnabled()) {
|
||||
await lastReplacement.attemptDecryption(this.client.crypto!);
|
||||
} else if (lastReplacement?.isBeingDecrypted()) {
|
||||
await lastReplacement.getDecryptionPromise();
|
||||
}
|
||||
|
||||
+1
-1
@@ -1604,7 +1604,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
||||
// find the earliest unfiltered timeline
|
||||
let timeline = unfilteredLiveTimeline;
|
||||
while (timeline.getNeighbouringTimeline(EventTimeline.BACKWARDS)) {
|
||||
timeline = timeline.getNeighbouringTimeline(EventTimeline.BACKWARDS);
|
||||
timeline = timeline.getNeighbouringTimeline(EventTimeline.BACKWARDS)!;
|
||||
}
|
||||
|
||||
timelineSet.getLiveTimeline().setPaginationToken(
|
||||
|
||||
@@ -83,7 +83,7 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
|
||||
|
||||
private reEmitter: TypedReEmitter<EmittedEvents, EventHandlerMap>;
|
||||
|
||||
private lastEvent: MatrixEvent;
|
||||
private lastEvent!: MatrixEvent;
|
||||
private replyCount = 0;
|
||||
|
||||
public readonly room: Room;
|
||||
@@ -185,7 +185,7 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
|
||||
this.lastEvent = events.find(e => (
|
||||
!e.isRedacted() &&
|
||||
e.isRelation(THREAD_RELATION_TYPE.name)
|
||||
)) ?? this.rootEvent;
|
||||
)) ?? this.rootEvent!;
|
||||
this.emit(ThreadEvent.Update, this);
|
||||
};
|
||||
|
||||
@@ -267,7 +267,7 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
|
||||
this.client.decryptEventIfNeeded(event, {});
|
||||
} else if (!toStartOfTimeline &&
|
||||
this.initialEventsFetched &&
|
||||
event.localTimestamp > this.lastReply()?.localTimestamp
|
||||
event.localTimestamp > this.lastReply()!.localTimestamp
|
||||
) {
|
||||
this.fetchEditsWhereNeeded(event);
|
||||
this.addEventToTimeline(event, false);
|
||||
@@ -289,7 +289,7 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
|
||||
}
|
||||
}
|
||||
|
||||
private getRootEventBundledRelationship(rootEvent = this.rootEvent): IThreadBundledRelationship {
|
||||
private getRootEventBundledRelationship(rootEvent = this.rootEvent): IThreadBundledRelationship | undefined {
|
||||
return rootEvent?.getServerAggregatedRelation<IThreadBundledRelationship>(THREAD_RELATION_TYPE.name);
|
||||
}
|
||||
|
||||
@@ -302,7 +302,7 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
|
||||
|
||||
if (Thread.hasServerSideSupport && bundledRelationship) {
|
||||
this.replyCount = bundledRelationship.count;
|
||||
this._currentUserParticipated = bundledRelationship.current_user_participated;
|
||||
this._currentUserParticipated = !!bundledRelationship.current_user_participated;
|
||||
|
||||
const event = new MatrixEvent({
|
||||
room_id: this.rootEvent.getRoomId(),
|
||||
@@ -407,7 +407,7 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
|
||||
}
|
||||
|
||||
public async fetchEvents(opts: IRelationsRequestOpts = { limit: 20, dir: Direction.Backward }): Promise<{
|
||||
originalEvent: MatrixEvent;
|
||||
originalEvent?: MatrixEvent;
|
||||
events: MatrixEvent[];
|
||||
nextBatch?: string | null;
|
||||
prevBatch?: string;
|
||||
@@ -427,7 +427,7 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
|
||||
|
||||
// When there's no nextBatch returned with a `from` request we have reached
|
||||
// the end of the thread, and therefore want to return an empty one
|
||||
if (!opts.to && !nextBatch) {
|
||||
if (!opts.to && !nextBatch && originalEvent) {
|
||||
events = [...events, originalEvent];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user