From 9d5ba4f681901a0ee241e542fa9be5e2b73f58db Mon Sep 17 00:00:00 2001
From: Nicolas Werner <nicolas.werner@hotmail.de>
Date: Mon, 19 Jul 2021 03:02:30 +0200
Subject: [PATCH] Move sticker parsing and enable room stickers

---
 resources/qml/emoji/StickerPicker.qml |  2 -
 src/Cache.cpp                         | 68 +++++++++++++++++++++++++--
 src/CacheStructs.h                    |  7 +++
 src/Cache_p.h                         |  8 +---
 src/ImagePackModel.cpp                | 31 ++----------
 5 files changed, 78 insertions(+), 38 deletions(-)

diff --git a/resources/qml/emoji/StickerPicker.qml b/resources/qml/emoji/StickerPicker.qml
index 3fe17ef26..ae1695dfa 100644
--- a/resources/qml/emoji/StickerPicker.qml
+++ b/resources/qml/emoji/StickerPicker.qml
@@ -38,8 +38,6 @@ Menu {
     modal: true
     focus: true
     closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
-    //height: columnView.implicitHeight + 4
-    //width: columnView.implicitWidth
     width: stickersPerRow * stickerDimPad + 20
 
     Rectangle {
diff --git a/src/Cache.cpp b/src/Cache.cpp
index 8c3d8c42c..4321393cc 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -3382,11 +3382,73 @@ Cache::getChildRoomIds(const std::string &room_id)
         return roomids;
 }
 
-std::optional<mtx::events::collections::RoomAccountDataEvents>
-Cache::getAccountData(mtx::events::EventType type, const std::string &room_id)
+std::vector<ImagePackInfo>
+Cache::getImagePacks(const std::string &room_id, bool stickers)
 {
         auto txn = ro_txn(env_);
-        return getAccountData(txn, type, room_id);
+        std::vector<ImagePackInfo> infos;
+
+        auto addPack = [&infos, stickers](const mtx::events::msc2545::ImagePack &pack) {
+                if (!pack.pack || (stickers ? pack.pack->is_sticker() : pack.pack->is_emoji())) {
+                        ImagePackInfo info;
+                        if (pack.pack)
+                                info.packname = pack.pack->display_name;
+
+                        for (const auto &img : pack.images) {
+                                if (img.second.overrides_usage() &&
+                                    (stickers ? !img.second.is_sticker() : !img.second.is_emoji()))
+                                        continue;
+
+                                info.images.insert(img);
+                        }
+
+                        if (!info.images.empty())
+                                infos.push_back(std::move(info));
+                }
+        };
+
+        // packs from account data
+        if (auto accountpack =
+              getAccountData(txn, mtx::events::EventType::ImagePackInAccountData, "")) {
+                auto tmp =
+                  std::get_if<mtx::events::EphemeralEvent<mtx::events::msc2545::ImagePack>>(
+                    &*accountpack);
+                if (tmp)
+                        addPack(tmp->content);
+        }
+
+        // packs from rooms, that were enabled globally
+        if (auto roomPacks = getAccountData(txn, mtx::events::EventType::ImagePackRooms, "")) {
+                auto tmp =
+                  std::get_if<mtx::events::EphemeralEvent<mtx::events::msc2545::ImagePackRooms>>(
+                    &*roomPacks);
+                if (tmp) {
+                        for (const auto &[room_id2, state_to_d] : tmp->content.rooms) {
+                                // don't add stickers from this room twice
+                                if (room_id2 == room_id)
+                                        continue;
+
+                                for (const auto &[state_id, d] : state_to_d) {
+                                        (void)d;
+                                        if (auto pack =
+                                              getStateEvent<mtx::events::msc2545::ImagePack>(
+                                                txn, room_id2))
+                                                addPack(pack->content);
+                                }
+                        }
+                }
+        }
+
+        // packs from current room
+        if (auto pack = getStateEvent<mtx::events::msc2545::ImagePack>(txn, room_id)) {
+                addPack(pack->content);
+        }
+        for (const auto &pack :
+             getStateEventsWithType<mtx::events::msc2545::ImagePack>(txn, room_id)) {
+                addPack(pack.content);
+        }
+
+        return infos;
 }
 
 std::optional<mtx::events::collections::RoomAccountDataEvents>
diff --git a/src/CacheStructs.h b/src/CacheStructs.h
index 28c70055d..f274d70fa 100644
--- a/src/CacheStructs.h
+++ b/src/CacheStructs.h
@@ -11,6 +11,7 @@
 #include <string>
 
 #include <mtx/events/join_rules.hpp>
+#include <mtx/events/mscs/image_packs.hpp>
 
 namespace cache {
 enum class CacheVersion : int
@@ -109,3 +110,9 @@ struct RoomSearchResult
         std::string room_id;
         RoomInfo info;
 };
+
+struct ImagePackInfo
+{
+        std::string packname;
+        std::map<std::string, mtx::events::msc2545::PackImage> images;
+};
diff --git a/src/Cache_p.h b/src/Cache_p.h
index 3752f5e43..13fbc371d 100644
--- a/src/Cache_p.h
+++ b/src/Cache_p.h
@@ -88,12 +88,6 @@ public:
         //! Retrieve if the room is a space
         bool getRoomIsSpace(lmdb::txn &txn, lmdb::dbi &statesdb);
 
-        //! retrieve a specific event from account data
-        //! pass empty room_id for global account data
-        std::optional<mtx::events::collections::RoomAccountDataEvents> getAccountData(
-          mtx::events::EventType type,
-          const std::string &room_id = "");
-
         //! Get a specific state event
         template<typename T>
         std::optional<mtx::events::StateEvent<T>> getStateEvent(const std::string &room_id,
@@ -231,6 +225,8 @@ public:
         std::vector<std::string> getParentRoomIds(const std::string &room_id);
         std::vector<std::string> getChildRoomIds(const std::string &room_id);
 
+        std::vector<ImagePackInfo> getImagePacks(const std::string &room_id, bool stickers);
+
         //! Mark a room that uses e2e encryption.
         void setEncryptedRoom(lmdb::txn &txn, const std::string &room_id);
         bool isRoomEncrypted(const std::string &room_id);
diff --git a/src/ImagePackModel.cpp b/src/ImagePackModel.cpp
index fb2599a5c..4345e3833 100644
--- a/src/ImagePackModel.cpp
+++ b/src/ImagePackModel.cpp
@@ -11,35 +11,12 @@ ImagePackModel::ImagePackModel(const std::string &roomId, bool stickers, QObject
   : QAbstractListModel(parent)
   , room_id(roomId)
 {
-        auto accountpackV =
-          cache::client()->getAccountData(mtx::events::EventType::ImagePackInAccountData);
-        auto enabledRoomPacksV =
-          cache::client()->getAccountData(mtx::events::EventType::ImagePackRooms);
+        auto packs = cache::client()->getImagePacks(room_id, stickers);
 
-        std::optional<mtx::events::msc2545::ImagePack> accountPack;
-        if (accountpackV) {
-                auto tmp =
-                  std::get_if<mtx::events::EphemeralEvent<mtx::events::msc2545::ImagePack>>(
-                    &*accountpackV);
-                if (tmp)
-                        accountPack = tmp->content;
-        }
-        // mtx::events::msc2545::ImagePackRooms *enabledRoomPacks = nullptr;
-        // if (enabledRoomPacksV)
-        //        enabledRoomPacks =
-        //          std::get_if<mtx::events::msc2545::ImagePackRooms>(&*enabledRoomPacksV);
-
-        if (accountPack && (!accountPack->pack || (stickers ? accountPack->pack->is_sticker()
-                                                            : accountPack->pack->is_emoji()))) {
-                QString packname;
-                if (accountPack->pack)
-                        packname = QString::fromStdString(accountPack->pack->display_name);
-
-                for (const auto &img : accountPack->images) {
-                        if (img.second.overrides_usage() &&
-                            (stickers ? !img.second.is_sticker() : !img.second.is_emoji()))
-                                continue;
+        for (const auto &pack : packs) {
+                QString packname = QString::fromStdString(pack.packname);
 
+                for (const auto &img : pack.images) {
                         ImageDesc i{};
                         i.shortcode = QString::fromStdString(img.first);
                         i.packname  = packname;
-- 
GitLab