summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2020-07-20 00:42:48 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2020-07-20 00:42:48 +0200
commit19f27236ea82b1927c83e4e24c71b30061674ee7 (patch)
tree1f6449488bbbd4dc23827253bbf56096f8f949e7
parentFix reaction display (diff)
downloadnheko-19f27236ea82b1927c83e4e24c71b30061674ee7.tar.xz
Fix reactions
-rw-r--r--resources/qml/Reactions.qml2
-rw-r--r--resources/qml/TimelineRow.qml1
-rw-r--r--resources/qml/TimelineView.qml7
-rw-r--r--resources/qml/emoji/EmojiButton.qml3
-rw-r--r--resources/qml/emoji/EmojiPicker.qml24
-rw-r--r--src/EventAccessors.cpp19
-rw-r--r--src/EventAccessors.h2
-rw-r--r--src/timeline/EventStore.cpp14
-rw-r--r--src/timeline/TimelineModel.cpp3
-rw-r--r--src/timeline/TimelineModel.h9
-rw-r--r--src/timeline/TimelineViewManager.cpp45
-rw-r--r--src/timeline/TimelineViewManager.h8
12 files changed, 89 insertions, 48 deletions
diff --git a/resources/qml/Reactions.qml b/resources/qml/Reactions.qml
index 5b3bbc20..c1091756 100644
--- a/resources/qml/Reactions.qml
+++ b/resources/qml/Reactions.qml
@@ -34,7 +34,7 @@ Flow {
 
 			onClicked: {
 				console.debug("Picked " + modelData.key + "in response to " + reactionFlow.eventId + " in room " + reactionFlow.roomId + ". selfReactedEvent: " + modelData.selfReactedEvent)
-				timelineManager.reactToMessage(reactionFlow.roomId, reactionFlow.eventId, modelData.key, modelData.selfReactedEvent)
+				timelineManager.queueReactionMessage(reactionFlow.eventId, modelData.key)
 			}
 
 
diff --git a/resources/qml/TimelineRow.qml b/resources/qml/TimelineRow.qml
index e87590f1..8186db8a 100644
--- a/resources/qml/TimelineRow.qml
+++ b/resources/qml/TimelineRow.qml
@@ -90,7 +90,6 @@ MouseArea {
 			ToolTip.visible: hovered
 			ToolTip.text: qsTr("React")
 			emojiPicker: emojiPopup
-			room_id: model.roomId
 			event_id: model.id
 		}
 		ImageButton {
diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml
index fd185bd9..1d7b4a4a 100644
--- a/resources/qml/TimelineView.qml
+++ b/resources/qml/TimelineView.qml
@@ -40,19 +40,20 @@ Page {
 		id: messageContextMenu
 		modal: true
 
-		function show(eventId_, eventType_, isEncrypted_, showAt) {
+		function show(eventId_, eventType_, isEncrypted_, showAt_) {
 			eventId = eventId_
 			eventType = eventType_
 			isEncrypted = isEncrypted_
-			popup(showAt)
+			popup(showAt_)
 		}
 
 		property string eventId
 		property int eventType
 		property bool isEncrypted
+
 		MenuItem {
 			text: qsTr("React")
-			onClicked: chat.model.reactAction(messageContextMenu.eventId)
+			onClicked: emojiPopup.show(messageContextMenu.parent, messageContextMenu.eventId)
 		}
 		MenuItem {
 			text: qsTr("Reply")
diff --git a/resources/qml/emoji/EmojiButton.qml b/resources/qml/emoji/EmojiButton.qml
index f8f75e3e..c5eee4e4 100644
--- a/resources/qml/emoji/EmojiButton.qml
+++ b/resources/qml/emoji/EmojiButton.qml
@@ -8,11 +8,10 @@ import "../"
 ImageButton {
     property var colors: currentActivePalette
     property var emojiPicker
-    property string room_id
     property string event_id
 
     image: ":/icons/icons/ui/smile.png"
     id: emojiButton
-    onClicked: emojiPicker.visible ? emojiPicker.close() : emojiPicker.show(emojiButton, room_id, event_id)
+    onClicked: emojiPicker.visible ? emojiPicker.close() : emojiPicker.show(emojiButton, event_id)
 
 }
diff --git a/resources/qml/emoji/EmojiPicker.qml b/resources/qml/emoji/EmojiPicker.qml
index ac67af2a..f75221d5 100644
--- a/resources/qml/emoji/EmojiPicker.qml
+++ b/resources/qml/emoji/EmojiPicker.qml
@@ -10,17 +10,17 @@ import "../"
 
 Popup {
 
-    function show(showAt, room_id, event_id) {
-        console.debug("Showing emojiPicker for " + event_id + "in room " + room_id)
-        parent = showAt
-        x = Math.round((showAt.width - width) / 2)
-        y = showAt.height
-        emojiPopup.room_id = room_id
-        emojiPopup.event_id = event_id
-        open()
-    }
+	function show(showAt, event_id) {
+		console.debug("Showing emojiPicker for " + event_id)
+		if (showAt){
+			parent = showAt
+			x = Math.round((showAt.width - width) / 2)
+			y = showAt.height
+		}
+		emojiPopup.event_id = event_id
+		open()
+	}
 
-    property string room_id
     property string event_id
     property var colors
     property alias model: gridView.model
@@ -102,9 +102,9 @@ Popup {
                 }
                 // TODO: maybe add favorites at some point?
                 onClicked: {
-                    console.debug("Picked " + model.unicode + "in response to " + emojiPopup.event_id + " in room " + emojiPopup.room_id)
+                    console.debug("Picked " + model.unicode + "in response to " + emojiPopup.event_id)
                     emojiPopup.close()
-                    timelineManager.queueReactionMessage(emojiPopup.room_id, emojiPopup.event_id, model.unicode)
+                    timelineManager.queueReactionMessage(emojiPopup.event_id, model.unicode)
                 }
             }
 
diff --git a/src/EventAccessors.cpp b/src/EventAccessors.cpp
index 7071819b..0618206c 100644
--- a/src/EventAccessors.cpp
+++ b/src/EventAccessors.cpp
@@ -223,6 +223,20 @@ struct EventInReplyTo
         }
 };
 
+struct EventRelatesTo
+{
+        template<class Content>
+        using related_ev_id_t = decltype(Content::relates_to.event_id);
+        template<class T>
+        std::string operator()(const mtx::events::Event<T> &e)
+        {
+                if constexpr (is_detected<related_ev_id_t, T>::value) {
+                        return e.content.relates_to.event_id;
+                }
+                return "";
+        }
+};
+
 struct EventTransactionId
 {
         template<class T>
@@ -378,6 +392,11 @@ mtx::accessors::in_reply_to_event(const mtx::events::collections::TimelineEvents
 {
         return std::visit(EventInReplyTo{}, event);
 }
+std::string
+mtx::accessors::relates_to_event_id(const mtx::events::collections::TimelineEvents &event)
+{
+        return std::visit(EventRelatesTo{}, event);
+}
 
 std::string
 mtx::accessors::transaction_id(const mtx::events::collections::TimelineEvents &event)
diff --git a/src/EventAccessors.h b/src/EventAccessors.h
index a7577d86..8f08ef1c 100644
--- a/src/EventAccessors.h
+++ b/src/EventAccessors.h
@@ -53,6 +53,8 @@ mimetype(const mtx::events::collections::TimelineEvents &event);
 std::string
 in_reply_to_event(const mtx::events::collections::TimelineEvents &event);
 std::string
+relates_to_event_id(const mtx::events::collections::TimelineEvents &event);
+std::string
 transaction_id(const mtx::events::collections::TimelineEvents &event);
 
 int64_t
diff --git a/src/timeline/EventStore.cpp b/src/timeline/EventStore.cpp
index 0bd7a97e..eb1162cc 100644
--- a/src/timeline/EventStore.cpp
+++ b/src/timeline/EventStore.cpp
@@ -202,6 +202,20 @@ EventStore::handleSync(const mtx::responses::Timeline &events)
                 if (auto redaction =
                       std::get_if<mtx::events::RedactionEvent<mtx::events::msg::Redaction>>(
                         &event)) {
+                        // fixup reactions
+                        auto redacted = events_by_id_.object({room_id_, redaction->redacts});
+                        if (redacted) {
+                                auto id = mtx::accessors::relates_to_event_id(*redacted);
+                                if (!id.empty()) {
+                                        auto idx = idToIndex(id);
+                                        if (idx) {
+                                                events_by_id_.remove(
+                                                  {room_id_, redaction->redacts});
+                                                emit dataChanged(*idx, *idx);
+                                        }
+                                }
+                        }
+
                         relates_to = redaction->redacts;
                 } else if (auto reaction =
                              std::get_if<mtx::events::RoomEvent<mtx::events::msg::Reaction>>(
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 85d2eb4e..8631eb83 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -1069,8 +1069,9 @@ struct SendMessageVisitor
         // reactions need to have the relation outside of ciphertext, or synapse / the homeserver
         // cannot handle it correctly.  See the MSC for more details:
         // https://github.com/matrix-org/matrix-doc/blob/matthew/msc1849/proposals/1849-aggregations.md#end-to-end-encryption
-        void operator()(const mtx::events::RoomEvent<mtx::events::msg::Reaction> &msg)
+        void operator()(mtx::events::RoomEvent<mtx::events::msg::Reaction> msg)
         {
+                msg.type = mtx::events::EventType::Reaction;
                 emit model_->addPendingMessageToStore(msg);
         }
 
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index cbe88fd2..f8a84f17 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -197,6 +197,15 @@ public:
         Q_INVOKABLE void cacheMedia(QString eventId);
         Q_INVOKABLE bool saveMedia(QString eventId) const;
 
+        std::vector<::Reaction> reactions(const std::string &event_id)
+        {
+                auto list = events.reactions(event_id);
+                std::vector<::Reaction> vec;
+                for (const auto &r : list)
+                        vec.push_back(r.value<Reaction>());
+                return vec;
+        }
+
         void updateLastMessage();
         void addEvents(const mtx::responses::Timeline &events);
         template<class T>
diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index 64af8afb..8cb72edd 100644
--- a/src/timeline/TimelineViewManager.cpp
+++ b/src/timeline/TimelineViewManager.cpp
@@ -314,36 +314,39 @@ TimelineViewManager::queueEmoteMessage(const QString &msg)
 }
 
 void
-TimelineViewManager::reactToMessage(const QString &roomId,
-                                    const QString &reactedEvent,
-                                    const QString &reactionKey,
-                                    const QString &selfReactedEvent)
+TimelineViewManager::queueReactionMessage(const QString &reactedEvent, const QString &reactionKey)
 {
+        if (!timeline_)
+                return;
+
+        auto reactions = timeline_->reactions(reactedEvent.toStdString());
+
+        QString selfReactedEvent;
+        for (const auto &reaction : reactions) {
+                if (reactionKey == reaction.key_) {
+                        selfReactedEvent = reaction.selfReactedEvent_;
+                        break;
+                }
+        }
+
+        if (selfReactedEvent.startsWith("m"))
+                return;
+
         // If selfReactedEvent is empty, that means we haven't previously reacted
         if (selfReactedEvent.isEmpty()) {
-                queueReactionMessage(roomId, reactedEvent, reactionKey);
+                mtx::events::msg::Reaction reaction;
+                reaction.relates_to.rel_type = mtx::common::RelationType::Annotation;
+                reaction.relates_to.event_id = reactedEvent.toStdString();
+                reaction.relates_to.key      = reactionKey.toStdString();
+
+                timeline_->sendMessage(reaction);
                 // Otherwise, we have previously reacted and the reaction should be redacted
         } else {
-                auto model = models.value(roomId);
-                model->redactEvent(selfReactedEvent);
+                timeline_->redactEvent(selfReactedEvent);
         }
 }
 
 void
-TimelineViewManager::queueReactionMessage(const QString &roomId,
-                                          const QString &reactedEvent,
-                                          const QString &reactionKey)
-{
-        mtx::events::msg::Reaction reaction;
-        reaction.relates_to.rel_type = mtx::common::RelationType::Annotation;
-        reaction.relates_to.event_id = reactedEvent.toStdString();
-        reaction.relates_to.key      = reactionKey.toStdString();
-
-        auto model = models.value(roomId);
-        model->sendMessage(reaction);
-}
-
-void
 TimelineViewManager::queueImageMessage(const QString &roomid,
                                        const QString &filename,
                                        const std::optional<mtx::crypto::EncryptedFile> &file,
diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h
index ed095058..63106916 100644
--- a/src/timeline/TimelineViewManager.h
+++ b/src/timeline/TimelineViewManager.h
@@ -61,13 +61,7 @@ public slots:
 
         void setHistoryView(const QString &room_id);
         void updateColorPalette();
-        void queueReactionMessage(const QString &roomId,
-                                  const QString &reactedEvent,
-                                  const QString &reaction);
-        void reactToMessage(const QString &roomId,
-                            const QString &reactedEvent,
-                            const QString &reactionKey,
-                            const QString &selfReactedEvent);
+        void queueReactionMessage(const QString &reactedEvent, const QString &reactionKey);
         void queueTextMessage(const QString &msg);
         void queueEmoteMessage(const QString &msg);
         void queueImageMessage(const QString &roomid,