diff --git a/src/domain/session/room/timeline/ReactionsViewModel.js b/src/domain/session/room/timeline/ReactionsViewModel.js index 6364fc8b..dea74ccf 100644 --- a/src/domain/session/room/timeline/ReactionsViewModel.js +++ b/src/domain/session/room/timeline/ReactionsViewModel.js @@ -22,6 +22,7 @@ export class ReactionsViewModel { this._reactions = this._map.sortValues((a, b) => a._compare(b)); } + /** @package */ update(annotations, pendingAnnotations) { if (annotations) { for (const key in annotations) { @@ -33,7 +34,7 @@ export class ReactionsViewModel { this._map.update(key); } } else { - this._map.add(key, new ReactionViewModel(key, annotation, null, this._parentEntry)); + this._map.add(key, new ReactionViewModel(key, annotation, 0, this._parentEntry)); } } } @@ -60,7 +61,7 @@ export class ReactionsViewModel { this._map.update(existingKey); } } else if (!hasPending) { - if (this._map.get(existingKey)._tryUpdatePending(null)) { + if (this._map.get(existingKey)._tryUpdatePending(0)) { this._map.update(existingKey); } } @@ -109,18 +110,15 @@ class ReactionViewModel { } get count() { - let count = 0; + let count = this._pendingCount; if (this._annotation) { count += this._annotation.count; } - if (this._pendingCount !== null) { - count += this._pendingCount; - } return count; } get isPending() { - return this._pendingCount !== null; + return this._pendingCount !== 0; } get haveReacted() { @@ -156,7 +154,6 @@ class ReactionViewModel { async toggleReaction() { if (this._isToggling) { - console.log("blocking toggleReaction, call ongoing"); return; } this._isToggling = true; diff --git a/src/matrix/room/timeline/Timeline.js b/src/matrix/room/timeline/Timeline.js index 35593663..c50523f3 100644 --- a/src/matrix/room/timeline/Timeline.js +++ b/src/matrix/room/timeline/Timeline.js @@ -22,7 +22,7 @@ import {TimelineReader} from "./persistence/TimelineReader.js"; import {PendingEventEntry} from "./entries/PendingEventEntry.js"; import {RoomMember} from "../members/RoomMember.js"; import {PowerLevels} from "./PowerLevels.js"; -import {getRelation, ANNOTATION_RELATION_TYPE} from "./relations.js"; +import {getRelation, getRelationFromContent, ANNOTATION_RELATION_TYPE} from "./relations.js"; import {REDACTION_TYPE} from "../common.js"; export class Timeline { @@ -116,19 +116,34 @@ export class Timeline { } async _mapPendingEventToEntry(pe) { - // we load the remote redaction target for pending events, + // we load the redaction target for pending events, // so if we are redacting a relation, we can pass the redaction // to the relation target and the removal of the relation can // be taken into account for local echo. - let redactionTarget; - if (pe.eventType === REDACTION_TYPE && pe.relatedEventId) { - const txn = await this._storage.readWriteTxn([ - this._storage.storeNames.timelineEvents, - ]); - const redactionTargetEntry = await txn.timelineEvents.getByEventId(this._roomId, pe.relatedEventId); - redactionTarget = redactionTargetEntry?.event; + let redactingRelation; + if (pe.eventType === REDACTION_TYPE) { + if (pe.relatedEventId) { + const txn = await this._storage.readWriteTxn([ + this._storage.storeNames.timelineEvents, + ]); + const redactionTargetEntry = await txn.timelineEvents.getByEventId(this._roomId, pe.relatedEventId); + if (redactionTargetEntry) { + redactingRelation = getRelation(redactionTargetEntry.event); + } + } else if (pe.relatedTxnId) { + // also look for redacting relation in pending events, in case the target is already being sent + for (const p of this._localEntries) { + if (p.id === pe.relatedTxnId) { + redactingRelation = getRelationFromContent(p.content); + break; + } + } + } } - const pee = new PendingEventEntry({pendingEvent: pe, member: this._ownMember, clock: this._clock, redactionTarget}); + const pee = new PendingEventEntry({ + pendingEvent: pe, member: this._ownMember, + clock: this._clock, redactingRelation + }); this._applyAndEmitLocalRelationChange(pee, target => target.addLocalRelation(pee)); return pee; } @@ -158,6 +173,7 @@ export class Timeline { // also look for a relation target to update with this redaction if (pee.redactingRelation) { const eventId = pee.redactingRelation.event_id; + // TODO: also support reacting to pending entries this._remoteEntries.findAndUpdate( e => e.id === eventId, updateOrFalse diff --git a/src/matrix/room/timeline/entries/PendingEventEntry.js b/src/matrix/room/timeline/entries/PendingEventEntry.js index d9aa4b80..edb728cd 100644 --- a/src/matrix/room/timeline/entries/PendingEventEntry.js +++ b/src/matrix/room/timeline/entries/PendingEventEntry.js @@ -19,13 +19,13 @@ import {BaseEventEntry} from "./BaseEventEntry.js"; import {getRelationFromContent} from "../relations.js"; export class PendingEventEntry extends BaseEventEntry { - constructor({pendingEvent, member, clock, redactionTarget}) { + constructor({pendingEvent, member, clock, redactingRelation}) { super(null); this._pendingEvent = pendingEvent; /** @type {RoomMember} */ this._member = member; this._clock = clock; - this._redactionTarget = redactionTarget; + this._redactingRelation = redactingRelation; } get fragmentId() { @@ -89,10 +89,7 @@ export class PendingEventEntry extends BaseEventEntry { } get redactingRelation() { - if (this._redactionTarget) { - return getRelationFromContent(this._redactionTarget.content); - } - return null; + return this._redactingRelation; } /** * returns either the relationship on this entry, @@ -100,10 +97,6 @@ export class PendingEventEntry extends BaseEventEntry { * * Useful while aggregating relations for local echo. */ get ownOrRedactedRelation() { - if (this._redactionTarget) { - return getRelationFromContent(this._redactionTarget.content); - } else { - return getRelationFromContent(this._pendingEvent.content); - } + return this.redactingRelation || getRelationFromContent(this._pendingEvent.content); } }