summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@ymail.com>2022-04-19 22:33:53 +0200
committerNicolas Werner <nicolas.werner@ymail.com>2022-04-19 22:33:53 +0200
commit3b2f47c56f56ce03cad92df8b6bc8dc1f4b583f6 (patch)
tree3a23b0017458f31cc8bfe46a21cfbcb4951af591
parentExplicitly install the configured files (diff)
downloadnheko-3b2f47c56f56ce03cad92df8b6bc8dc1f4b583f6.tar.xz
Show changes in image packs in timeline
Diffstat (limited to '')
-rw-r--r--resources/qml/delegates/MessageDelegate.qml4
-rw-r--r--src/timeline/TimelineModel.cpp69
-rw-r--r--src/timeline/TimelineModel.h1
3 files changed, 72 insertions, 2 deletions
diff --git a/resources/qml/delegates/MessageDelegate.qml b/resources/qml/delegates/MessageDelegate.qml
index 0e211ded..44da16bf 100644
--- a/resources/qml/delegates/MessageDelegate.qml
+++ b/resources/qml/delegates/MessageDelegate.qml
@@ -284,11 +284,12 @@ Item {
                 isOnlyEmoji: false
                 isReply: d.isReply
                 isStateEvent: d.isStateEvent
-                formatted: qsTr("%1 changed the stickers and emotes in this room.").arg(d.userName)
+                formatted: d.relatedEventCacheBuster, room.formatImagePackEvent(d.eventId)
             }
 
         }
 
+
         DelegateChoice {
             roleValue: MtxEvent.CanonicalAlias
 
@@ -390,7 +391,6 @@ Item {
         }
 
         DelegateChoice {
-            // TODO: make a more complex formatter for the power levels.
             roleValue: MtxEvent.PowerLevels
 
             NoticeMessage {
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 8d7b7919..9c12b967 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -197,6 +197,12 @@ qml_mtx_events::toRoomEventType(mtx::events::EventType e)
         return qml_mtx_events::EventType::SpaceParent;
     case EventType::SpaceChild:
         return qml_mtx_events::EventType::SpaceChild;
+    case EventType::ImagePackInRoom:
+        return qml_mtx_events::ImagePackInRoom;
+    case EventType::ImagePackInAccountData:
+        return qml_mtx_events::ImagePackInAccountData;
+    case EventType::ImagePackRooms:
+        return qml_mtx_events::ImagePackRooms;
     case EventType::Unsupported:
         return qml_mtx_events::EventType::Unsupported;
     default:
@@ -2201,6 +2207,69 @@ TimelineModel::formatPowerLevelEvent(const QString &id)
     }
 }
 
+QString
+TimelineModel::formatImagePackEvent(const QString &id)
+{
+    mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
+    if (!e)
+        return {};
+
+    auto event = std::get_if<mtx::events::StateEvent<mtx::events::msc2545::ImagePack>>(e);
+    if (!event)
+        return {};
+
+    mtx::events::StateEvent<mtx::events::msc2545::ImagePack> *prevEvent = nullptr;
+    if (!event->unsigned_data.replaces_state.empty()) {
+        auto tempPrevEvent = events.get(event->unsigned_data.replaces_state, event->event_id);
+        if (tempPrevEvent) {
+            prevEvent =
+              std::get_if<mtx::events::StateEvent<mtx::events::msc2545::ImagePack>>(tempPrevEvent);
+        }
+    }
+
+    const auto &newImages = event->content.images;
+    const auto oldImages  = prevEvent ? prevEvent->content.images : decltype(newImages){};
+
+    auto ascent = QFontMetrics(UserSettings::instance()->font()).ascent();
+
+    auto calcChange = [ascent](const std::map<std::string, mtx::events::msc2545::PackImage> &newI,
+                               const std::map<std::string, mtx::events::msc2545::PackImage> &oldI) {
+        QStringList added;
+        for (const auto &[shortcode, img] : newI) {
+            if (!oldI.count(shortcode))
+                added.push_back(QStringLiteral("<img data-mx-emoticon height=%1 src=\"%2\"> (~%3)")
+                                  .arg(ascent)
+                                  .arg(QString::fromStdString(img.url)
+                                         .replace("mxc://", "image://mxcImage/")
+                                         .toHtmlEscaped(),
+                                       QString::fromStdString(shortcode)));
+        }
+        return added;
+    };
+
+    auto added   = calcChange(newImages, oldImages);
+    auto removed = calcChange(oldImages, newImages);
+
+    auto sender = utils::replaceEmoji(displayName(QString::fromStdString(event->sender)));
+
+    QString msg;
+
+    if (!removed.isEmpty()) {
+        msg = tr("%1 removed the following images from the pack:<br>%2")
+                .arg(sender, removed.join(", "));
+    }
+    if (!added.isEmpty()) {
+        if (!msg.isEmpty())
+            msg += "<br>";
+        msg += tr("%1 added the following images to the pack:<br>%2").arg(sender, added.join(", "));
+    }
+
+    if (msg.isEmpty())
+        return tr("%1 changed the sticker and emotes in this room.").arg(sender);
+    else
+        return msg;
+}
+
 QVariantMap
 TimelineModel::formatRedactedEvent(const QString &id)
 {
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index 7e21a394..c52473b1 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -262,6 +262,7 @@ public:
     Q_INVOKABLE QString formatHistoryVisibilityEvent(const QString &id);
     Q_INVOKABLE QString formatGuestAccessEvent(const QString &id);
     Q_INVOKABLE QString formatPowerLevelEvent(const QString &id);
+    Q_INVOKABLE QString formatImagePackEvent(const QString &id);
     Q_INVOKABLE QVariantMap formatRedactedEvent(const QString &id);
 
     Q_INVOKABLE void viewRawMessage(const QString &id);