diff --git a/src/matrix/room/timeline/entries/BaseEntry.js b/src/matrix/room/timeline/entries/BaseEntry.ts similarity index 81% rename from src/matrix/room/timeline/entries/BaseEntry.js rename to src/matrix/room/timeline/entries/BaseEntry.ts index ae3ddf05..2a6b9b5d 100644 --- a/src/matrix/room/timeline/entries/BaseEntry.js +++ b/src/matrix/room/timeline/entries/BaseEntry.ts @@ -18,20 +18,26 @@ limitations under the License. import {EventKey} from "../EventKey.js"; export const PENDING_FRAGMENT_ID = Number.MAX_SAFE_INTEGER; -export class BaseEntry { +export interface FragmentIdComparer { + compare(a: number, b: number): number; +} + +export abstract class BaseEntry { + protected _fragmentIdComparer: FragmentIdComparer + constructor(fragmentIdComparer) { this._fragmentIdComparer = fragmentIdComparer; } - get fragmentId() { + get fragmentId(): number { throw new Error("unimplemented"); } - get entryIndex() { + get entryIndex(): number { throw new Error("unimplemented"); } - compare(otherEntry) { + compare(otherEntry: BaseEntry): number { if (this.fragmentId === otherEntry.fragmentId) { return this.entryIndex - otherEntry.entryIndex; } else if (this.fragmentId === PENDING_FRAGMENT_ID) { @@ -44,9 +50,9 @@ export class BaseEntry { } } - asEventKey() { + asEventKey(): EventKey { return new EventKey(this.fragmentId, this.entryIndex); } - updateFrom() {} + updateFrom(other: BaseEntry) {} } diff --git a/src/matrix/room/timeline/entries/BaseEventEntry.js b/src/matrix/room/timeline/entries/BaseEventEntry.ts similarity index 78% rename from src/matrix/room/timeline/entries/BaseEventEntry.js rename to src/matrix/room/timeline/entries/BaseEventEntry.ts index 2e681104..79a453a0 100644 --- a/src/matrix/room/timeline/entries/BaseEventEntry.js +++ b/src/matrix/room/timeline/entries/BaseEventEntry.ts @@ -14,33 +14,48 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseEntry} from "./BaseEntry.js"; +import {FragmentIdComparer, BaseEntry} from "./BaseEntry"; +import {PendingEventEntry} from "./PendingEventEntry.js" import {REDACTION_TYPE} from "../../common.js"; import {createAnnotation, ANNOTATION_RELATION_TYPE, getRelationFromContent} from "../relations.js"; import {PendingAnnotation} from "../PendingAnnotation.js"; +export interface Annotation { + count: number, + me: boolean, + firstTimestamp: number +} + /** Deals mainly with local echo for relations and redactions, * so it is shared between PendingEventEntry and EventEntry */ -export class BaseEventEntry extends BaseEntry { - constructor(fragmentIdComparer) { +export abstract class BaseEventEntry extends BaseEntry { + private _pendingRedactions: Array | null + private _pendingAnnotations: Map | null + + abstract id: string + abstract relatedEventId: string + abstract eventType: string + abstract content: any + + constructor(fragmentIdComparer: FragmentIdComparer) { super(fragmentIdComparer); this._pendingRedactions = null; this._pendingAnnotations = null; } - get isRedacting() { + get isRedacting(): boolean { return !!this._pendingRedactions; } - get isRedacted() { + get isRedacted(): boolean { return this.isRedacting; } - get isRedaction() { + get isRedaction(): boolean { return this.eventType === REDACTION_TYPE; } - get redactionReason() { + get redactionReason(): string | null { if (this._pendingRedactions) { return this._pendingRedactions[0].content?.reason; } @@ -51,7 +66,7 @@ export class BaseEventEntry extends BaseEntry { aggregates local relation or local redaction of remote relation. @return [string] returns the name of the field that has changed, if any */ - addLocalRelation(entry) { + addLocalRelation(entry: PendingEventEntry): string | undefined { if (entry.eventType === REDACTION_TYPE && entry.isRelatedToId(this.id)) { if (!this._pendingRedactions) { this._pendingRedactions = []; @@ -76,7 +91,7 @@ export class BaseEventEntry extends BaseEntry { deaggregates local relation or a local redaction of a remote relation. @return [string] returns the name of the field that has changed, if any */ - removeLocalRelation(entry) { + removeLocalRelation(entry: PendingEventEntry): string | undefined { if (entry.eventType === REDACTION_TYPE && entry.isRelatedToId(this.id) && this._pendingRedactions) { const countBefore = this._pendingRedactions.length; this._pendingRedactions = this._pendingRedactions.filter(e => e !== entry); @@ -98,7 +113,7 @@ export class BaseEventEntry extends BaseEntry { } } - _addPendingAnnotation(entry) { + _addPendingAnnotation(entry: PendingEventEntry): boolean { if (!this._pendingAnnotations) { this._pendingAnnotations = new Map(); } @@ -115,14 +130,14 @@ export class BaseEventEntry extends BaseEntry { return false; } - _removePendingAnnotation(entry) { + _removePendingAnnotation(entry: PendingEventEntry) { const {key} = (entry.redactingEntry || entry).relation; if (key) { - let annotation = this._pendingAnnotations.get(key); + let annotation = this._pendingAnnotations?.get(key); if (annotation.remove(entry) && annotation.isEmpty) { - this._pendingAnnotations.delete(key); + this._pendingAnnotations?.delete(key); } - if (this._pendingAnnotations.size === 0) { + if (this._pendingAnnotations?.size === 0) { this._pendingAnnotations = null; } return true; @@ -140,23 +155,23 @@ export class BaseEventEntry extends BaseEntry { } } - get pendingRedaction() { + get pendingRedaction(): PendingEventEntry | null { if (this._pendingRedactions) { return this._pendingRedactions[0]; } return null; } - annotate(key) { + annotate(key: string): any { return createAnnotation(this.id, key); } /** takes both remote event id and local txn id into account, see overriding in PendingEventEntry */ - isRelatedToId(id) { - return id && this.relatedEventId === id; + isRelatedToId(id: string | null): boolean { + return !!id && this.relatedEventId === id; } - haveAnnotation(key) { + haveAnnotation(key: string): boolean { const haveRemoteReaction = this.annotations?.[key]?.me || false; const pendingAnnotation = this.pendingAnnotations?.get(key); const willAnnotate = pendingAnnotation?.willAnnotate || false; @@ -170,15 +185,15 @@ export class BaseEventEntry extends BaseEntry { (!haveRemoteReaction && willAnnotate); } - get relation() { + get relation(): any { return getRelationFromContent(this.content); } - get pendingAnnotations() { + get pendingAnnotations(): Map | null { return this._pendingAnnotations; } - get annotations() { + get annotations(): { [key: string]: Annotation } | null { return null; //overwritten in EventEntry } } diff --git a/src/matrix/room/timeline/entries/EventEntry.js b/src/matrix/room/timeline/entries/EventEntry.ts similarity index 95% rename from src/matrix/room/timeline/entries/EventEntry.js rename to src/matrix/room/timeline/entries/EventEntry.ts index f98801f9..0d48c3f2 100644 --- a/src/matrix/room/timeline/entries/EventEntry.js +++ b/src/matrix/room/timeline/entries/EventEntry.ts @@ -14,25 +14,30 @@ See the License for the specific language governing permissions and limitations under the License. */ +import {FragmentIdComparer} from "./BaseEntry.js" import {BaseEventEntry} from "./BaseEventEntry.js"; import {getPrevContentFromStateEvent, isRedacted} from "../../common.js"; import {getRelatedEventId} from "../relations.js"; export class EventEntry extends BaseEventEntry { - constructor(eventEntry, fragmentIdComparer) { + private _eventEntry: any // TODO Need type + private _decryptionError: Error | null + private _decryptionResult: any | null // TODO Need type + + constructor(eventEntry: any, fragmentIdComparer: FragmentIdComparer = { compare: (x, y) => 0 }) { super(fragmentIdComparer); this._eventEntry = eventEntry; this._decryptionError = null; this._decryptionResult = null; } - clone() { + clone(): EventEntry { const clone = new EventEntry(this._eventEntry, this._fragmentIdComparer); clone.updateFrom(this); return clone; } - updateFrom(other) { + updateFrom(other: EventEntry) { super.updateFrom(other); if (other._decryptionResult && !this._decryptionResult) { this._decryptionResult = other._decryptionResult; diff --git a/src/matrix/room/timeline/entries/PendingEventEntry.js b/src/matrix/room/timeline/entries/PendingEventEntry.js index 742bff49..2c543e8e 100644 --- a/src/matrix/room/timeline/entries/PendingEventEntry.js +++ b/src/matrix/room/timeline/entries/PendingEventEntry.js @@ -14,8 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {PENDING_FRAGMENT_ID} from "./BaseEntry.js"; -import {BaseEventEntry} from "./BaseEventEntry.js"; +import {PENDING_FRAGMENT_ID} from "./BaseEntry"; +import {BaseEventEntry} from "./BaseEventEntry"; export class PendingEventEntry extends BaseEventEntry { constructor({pendingEvent, member, clock, redactingEntry}) {