WIP2
This commit is contained in:
parent
2ebadb36c3
commit
206d18f498
10 changed files with 67 additions and 42 deletions
|
@ -79,6 +79,7 @@ class ReactionViewModel {
|
||||||
this._annotation = annotation;
|
this._annotation = annotation;
|
||||||
this._pendingCount = pendingCount;
|
this._pendingCount = pendingCount;
|
||||||
this._parentEntry = parentEntry;
|
this._parentEntry = parentEntry;
|
||||||
|
this._isToggling = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_tryUpdate(annotation) {
|
_tryUpdate(annotation) {
|
||||||
|
@ -143,14 +144,24 @@ class ReactionViewModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleReaction() {
|
async toggleReaction() {
|
||||||
const havePendingReaction = this._pendingCount > 0;
|
if (this._isToggling) {
|
||||||
const haveRemoteReaction = this._annotation?.me;
|
console.log("blocking toggleReaction, call ongoing");
|
||||||
const haveReaction = havePendingReaction || haveRemoteReaction;
|
return;
|
||||||
if (haveReaction) {
|
}
|
||||||
return this._parentEntry.redactReaction(this.key);
|
this._isToggling = true;
|
||||||
} else {
|
try {
|
||||||
return this._parentEntry.react(this.key);
|
const haveLocalRedaction = this._pendingCount < 0;
|
||||||
|
const havePendingReaction = this._pendingCount > 0;
|
||||||
|
const haveRemoteReaction = this._annotation?.me;
|
||||||
|
const haveReaction = havePendingReaction || (haveRemoteReaction && !haveLocalRedaction);
|
||||||
|
if (haveReaction) {
|
||||||
|
await this._parentEntry.redactReaction(this.key);
|
||||||
|
} else {
|
||||||
|
await this._parentEntry.react(this.key);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
this._isToggling = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,27 +124,23 @@ export class BaseMessageTile extends SimpleTile {
|
||||||
}
|
}
|
||||||
|
|
||||||
react(key, log = null) {
|
react(key, log = null) {
|
||||||
return this.logger.wrapOrRun(log, "react", log => {
|
return this.logger.wrapOrRun(log, "react", async log => {
|
||||||
// this assumes the existing reaction is not a remote one
|
const existingAnnotation = await this._entry.getOwnAnnotationEntry(this._timeline, key);
|
||||||
// we would need to do getOwnAnnotation(Id) and see if there are any pending redactions for it
|
const redaction = existingAnnotation?.pendingRedaction;
|
||||||
const pee = this._entry.getPendingAnnotationEntry(key);
|
if (redaction && !redaction.pendingEvent.hasStartedSending) {
|
||||||
const redaction = pee?.pendingRedaction;
|
|
||||||
log.set("has_redaction", !!redaction);
|
|
||||||
log.set("has_redaction", !!redaction);
|
|
||||||
if (redaction && !redaction.hasStartedSending) {
|
|
||||||
log.set("abort_redaction", true);
|
log.set("abort_redaction", true);
|
||||||
return redaction.pendingEvent.abort();
|
await redaction.pendingEvent.abort();
|
||||||
} else {
|
} else {
|
||||||
return this._room.sendEvent("m.reaction", this._entry.annotate(key), null, log);
|
await this._room.sendEvent("m.reaction", this._entry.annotate(key), null, log);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async redactReaction(key, log = null) {
|
redactReaction(key, log = null) {
|
||||||
return this.logger.wrapOrRun(log, "redactReaction", log => {
|
return this.logger.wrapOrRun(log, "redactReaction", async log => {
|
||||||
const id = await this._entry.getOwnAnnotationId(this._room, key);
|
const entry = await this._entry.getOwnAnnotationEntry(this._timeline, key);
|
||||||
if (id) {
|
if (entry) {
|
||||||
this._room.sendRedaction(id, null, log);
|
await this._room.sendRedaction(entry.id, null, log);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,8 +129,12 @@ export class SimpleTile extends ViewModel {
|
||||||
return this._options.room;
|
return this._options.room;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get _timeline() {
|
||||||
|
return this._options.timeline;
|
||||||
|
}
|
||||||
|
|
||||||
get _powerLevels() {
|
get _powerLevels() {
|
||||||
return this._options.timeline.powerLevels;
|
return this._timeline.powerLevels;
|
||||||
}
|
}
|
||||||
|
|
||||||
get _ownMember() {
|
get _ownMember() {
|
||||||
|
|
|
@ -452,7 +452,7 @@ export class BaseRoom extends EventEmitter {
|
||||||
return observable;
|
return observable;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getOwnAnnotationEventId(targetId, key) {
|
async getOwnAnnotationEntry(targetId, key) {
|
||||||
const txn = await this._storage.readWriteTxn([
|
const txn = await this._storage.readWriteTxn([
|
||||||
this._storage.storeNames.timelineEvents,
|
this._storage.storeNames.timelineEvents,
|
||||||
this._storage.storeNames.timelineRelations,
|
this._storage.storeNames.timelineRelations,
|
||||||
|
@ -461,7 +461,9 @@ export class BaseRoom extends EventEmitter {
|
||||||
for (const relation of relations) {
|
for (const relation of relations) {
|
||||||
const annotation = await txn.timelineEvents.getByEventId(this.id, relation.sourceEventId);
|
const annotation = await txn.timelineEvents.getByEventId(this.id, relation.sourceEventId);
|
||||||
if (annotation.event.sender === this._user.id && getRelation(annotation.event).key === key) {
|
if (annotation.event.sender === this._user.id && getRelation(annotation.event).key === key) {
|
||||||
return annotation.event.event_id;
|
const eventEntry = new EventEntry(annotation, this._fragmentIdComparer);
|
||||||
|
// add local relations
|
||||||
|
return eventEntry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -303,7 +303,7 @@ export class Room extends BaseRoom {
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
sendEvent(eventType, content, attachments, log = null) {
|
sendEvent(eventType, content, attachments, log = null) {
|
||||||
this._platform.logger.wrapOrRun(log, "send", log => {
|
return this._platform.logger.wrapOrRun(log, "send", log => {
|
||||||
log.set("id", this.id);
|
log.set("id", this.id);
|
||||||
return this._sendQueue.enqueueEvent(eventType, content, attachments, log);
|
return this._sendQueue.enqueueEvent(eventType, content, attachments, log);
|
||||||
});
|
});
|
||||||
|
@ -311,7 +311,7 @@ export class Room extends BaseRoom {
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
sendRedaction(eventIdOrTxnId, reason, log = null) {
|
sendRedaction(eventIdOrTxnId, reason, log = null) {
|
||||||
this._platform.logger.wrapOrRun(log, "redact", log => {
|
return this._platform.logger.wrapOrRun(log, "redact", log => {
|
||||||
log.set("id", this.id);
|
log.set("id", this.id);
|
||||||
return this._sendQueue.enqueueRedaction(eventIdOrTxnId, reason, log);
|
return this._sendQueue.enqueueRedaction(eventIdOrTxnId, reason, log);
|
||||||
});
|
});
|
||||||
|
|
|
@ -117,7 +117,7 @@ export class PendingEvent {
|
||||||
get error() { return this._error; }
|
get error() { return this._error; }
|
||||||
|
|
||||||
get hasStartedSending() {
|
get hasStartedSending() {
|
||||||
return this._status !== SendStatus.Sending && this._status !== SendStatus.Sent;
|
return this._status === SendStatus.Sending || this._status === SendStatus.Sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
get attachmentsTotalBytes() {
|
get attachmentsTotalBytes() {
|
||||||
|
|
|
@ -22,7 +22,7 @@ import {TimelineReader} from "./persistence/TimelineReader.js";
|
||||||
import {PendingEventEntry} from "./entries/PendingEventEntry.js";
|
import {PendingEventEntry} from "./entries/PendingEventEntry.js";
|
||||||
import {RoomMember} from "../members/RoomMember.js";
|
import {RoomMember} from "../members/RoomMember.js";
|
||||||
import {PowerLevels} from "./PowerLevels.js";
|
import {PowerLevels} from "./PowerLevels.js";
|
||||||
import {getRelationFromContent} from "./relations.js";
|
import {getRelationFromContent, getRelation, ANNOTATION_RELATION_TYPE} from "./relations.js";
|
||||||
|
|
||||||
export class Timeline {
|
export class Timeline {
|
||||||
constructor({roomId, storage, closeCallback, fragmentIdComparer, pendingEvents, clock}) {
|
constructor({roomId, storage, closeCallback, fragmentIdComparer, pendingEvents, clock}) {
|
||||||
|
@ -124,7 +124,6 @@ export class Timeline {
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
});
|
});
|
||||||
console.log("redactedEntry", redactedEntry);
|
|
||||||
if (redactedEntry) {
|
if (redactedEntry) {
|
||||||
const redactedRelation = getRelationFromContent(redactedEntry.content);
|
const redactedRelation = getRelationFromContent(redactedEntry.content);
|
||||||
if (redactedRelation?.event_id) {
|
if (redactedRelation?.event_id) {
|
||||||
|
@ -132,7 +131,6 @@ export class Timeline {
|
||||||
e => e.id === redactedRelation.event_id,
|
e => e.id === redactedRelation.event_id,
|
||||||
relationTarget => relationTarget.addLocalRelation(redactedEntry) || false
|
relationTarget => relationTarget.addLocalRelation(redactedEntry) || false
|
||||||
);
|
);
|
||||||
console.log("found", found);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,6 +180,24 @@ export class Timeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async getOwnAnnotationEntry(targetId, key) {
|
||||||
|
const txn = await this._storage.readWriteTxn([
|
||||||
|
this._storage.storeNames.timelineEvents,
|
||||||
|
this._storage.storeNames.timelineRelations,
|
||||||
|
]);
|
||||||
|
const relations = await txn.timelineRelations.getForTargetAndType(this._roomId, targetId, ANNOTATION_RELATION_TYPE);
|
||||||
|
for (const relation of relations) {
|
||||||
|
const annotation = await txn.timelineEvents.getByEventId(this._roomId, relation.sourceEventId);
|
||||||
|
if (annotation.event.sender === this._ownMember.userId && getRelation(annotation.event).key === key) {
|
||||||
|
const eventEntry = new EventEntry(annotation, this._fragmentIdComparer);
|
||||||
|
this._addLocalRelationsToNewRemoteEntries([eventEntry]);
|
||||||
|
return eventEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
updateOwnMember(member) {
|
updateOwnMember(member) {
|
||||||
this._ownMember = member;
|
this._ownMember = member;
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,11 +117,7 @@ export class BaseEventEntry extends BaseEntry {
|
||||||
return this._pendingAnnotations?.aggregatedAnnotations;
|
return this._pendingAnnotations?.aggregatedAnnotations;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getOwnAnnotationId(room, key) {
|
async getOwnAnnotationEntry(timeline, key) {
|
||||||
return this.getPendingAnnotationEntry(key)?.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
getPendingAnnotationEntry(key) {
|
|
||||||
return this._pendingAnnotations?.findForKey(key);
|
return this._pendingAnnotations?.findForKey(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,12 +131,12 @@ export class EventEntry extends BaseEventEntry {
|
||||||
return this._eventEntry.annotations;
|
return this._eventEntry.annotations;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getOwnAnnotationId(room, key) {
|
async getOwnAnnotationEntry(timeline, key) {
|
||||||
const localId = await super.getOwnAnnotationId(room, key);
|
const localId = await super.getOwnAnnotationEntry(timeline, key);
|
||||||
if (localId) {
|
if (localId) {
|
||||||
return localId;
|
return localId;
|
||||||
} else {
|
} else {
|
||||||
return room.getOwnAnnotationEventId(this.id, key);
|
return timeline.getOwnAnnotationEntry(this.id, key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -243,7 +243,7 @@ only loads when the top comes into view*/
|
||||||
|
|
||||||
.Timeline_messageReactions button.haveReacted.isPending {
|
.Timeline_messageReactions button.haveReacted.isPending {
|
||||||
animation-name: glow-reaction-border;
|
animation-name: glow-reaction-border;
|
||||||
animation-duration: 1s;
|
animation-duration: 0.8s;
|
||||||
animation-direction: alternate;
|
animation-direction: alternate;
|
||||||
animation-iteration-count: infinite;
|
animation-iteration-count: infinite;
|
||||||
animation-timing-function: linear;
|
animation-timing-function: linear;
|
||||||
|
|
Reference in a new issue