support undoing a reaction

This commit is contained in:
Bruno Windels 2021-06-03 19:57:16 +02:00
parent 20abb01ee8
commit bb8acbefa3
7 changed files with 45 additions and 5 deletions

View file

@ -86,7 +86,11 @@ class ReactionViewModel extends ViewModel {
return this._annotation.count - other._annotation.count; return this._annotation.count - other._annotation.count;
} }
react() { toggleReaction() {
if (this.haveReacted) {
return this._parentEntry.redactReaction(this.key);
} else {
return this._parentEntry.react(this.key); return this._parentEntry.react(this.key);
} }
} }
}

View file

@ -123,7 +123,14 @@ export class BaseMessageTile extends SimpleTile {
} }
react(key) { react(key) {
this._room.sendEvent("m.reaction", this._entry.annotate(key)); return this._room.sendEvent("m.reaction", this._entry.annotate(key));
}
async redactReaction(key) {
const id = await this._entry.getOwnAnnotationId(this._room, key);
if (id) {
this._room.sendRedaction(id);
}
} }
_updateReactions() { _updateReactions() {

View file

@ -28,6 +28,7 @@ import {EventEntry} from "./timeline/entries/EventEntry.js";
import {ObservedEventMap} from "./ObservedEventMap.js"; import {ObservedEventMap} from "./ObservedEventMap.js";
import {DecryptionSource} from "../e2ee/common.js"; import {DecryptionSource} from "../e2ee/common.js";
import {ensureLogItem} from "../../logging/utils.js"; import {ensureLogItem} from "../../logging/utils.js";
import {ANNOTATION_RELATION_TYPE, getRelation} from "./timeline/relations.js";
const EVENT_ENCRYPTED_TYPE = "m.room.encrypted"; const EVENT_ENCRYPTED_TYPE = "m.room.encrypted";
@ -451,6 +452,21 @@ export class BaseRoom extends EventEmitter {
return observable; return observable;
} }
async getOwnAnnotationEventId(targetId, key) {
const txn = await this._storage.readWriteTxn([
this._storage.storeNames.timelineEvents,
this._storage.storeNames.timelineRelations,
]);
const relations = await txn.timelineRelations.getForTargetAndType(this.id, targetId, ANNOTATION_RELATION_TYPE);
for (const relation of relations) {
const annotation = await txn.timelineEvents.getByEventId(this.id, relation.sourceEventId);
if (annotation.event.sender === this._user.id && getRelation(annotation.event).key === key) {
return annotation.event.event_id;
}
}
return null;
}
async _readEventById(eventId) { async _readEventById(eventId) {
let stores = [this._storage.storeNames.timelineEvents]; let stores = [this._storage.storeNames.timelineEvents];
if (this.isEncrypted) { if (this.isEncrypted) {

View file

@ -130,4 +130,8 @@ export class EventEntry extends BaseEventEntry {
get annotations() { get annotations() {
return this._eventEntry.annotations; return this._eventEntry.annotations;
} }
getOwnAnnotationId(room, key) {
return room.getOwnAnnotationEventId(this.id, key);
}
} }

View file

@ -85,4 +85,9 @@ export class PendingEventEntry extends BaseEventEntry {
get relatedEventId() { get relatedEventId() {
return this._pendingEvent.relatedEventId; return this._pendingEvent.relatedEventId;
} }
getOwnAnnotationId(_, key) {
// TODO: implement this once local reactions are implemented
return null;
}
} }

View file

@ -217,6 +217,11 @@ only loads when the top comes into view*/
grid-area: reactions; grid-area: reactions;
} }
.Timeline_messageReactions button.haveReacted {
background-color: green;
color: white;
}
.AnnouncementView { .AnnouncementView {
margin: 5px 0; margin: 5px 0;
padding: 5px 10%; padding: 5px 10%;

View file

@ -32,12 +32,11 @@ class ReactionView extends TemplateView {
render(t, vm) { render(t, vm) {
const haveReacted = vm => vm.haveReacted; const haveReacted = vm => vm.haveReacted;
return t.button({ return t.button({
disabled: haveReacted,
className: {haveReacted}, className: {haveReacted},
}, [vm.key, " ", vm => `${vm.count}`]); }, [vm.key, " ", vm => `${vm.count}`]);
} }
onClick() { onClick() {
this.value.react(); this.value.toggleReaction();
} }
} }