diff --git a/resources/qml/dialogs/ImagePackSettingsDialog.qml b/resources/qml/dialogs/ImagePackSettingsDialog.qml index 24f70f68..2bbcfe54 100644 --- a/resources/qml/dialogs/ImagePackSettingsDialog.qml +++ b/resources/qml/dialogs/ImagePackSettingsDialog.qml @@ -105,6 +105,7 @@ ApplicationWindow { required property string displayName required property bool fromAccountData required property bool fromCurrentRoom + required property bool fromSpace required property string statekey title: displayName @@ -113,6 +114,8 @@ ApplicationWindow { return qsTr("Private pack"); else if (fromCurrentRoom) return qsTr("Pack from this room"); + else if (fromSpace) + return qsTr("Pack from parent community"); else return qsTr("Globally enabled pack"); } diff --git a/src/Cache.cpp b/src/Cache.cpp index ede2e4e5..bf485325 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -8,6 +8,7 @@ #include "Cache_p.h" #include +#include #include #include @@ -3911,7 +3912,8 @@ Cache::getImagePacks(const std::string &room_id, std::optional stickers) auto addPack = [&infos, stickers](const mtx::events::msc2545::ImagePack &pack, const std::string &source_room, - const std::string &state_key) { + const std::string &state_key, + bool from_space) { bool pack_is_sticker = pack.pack ? pack.pack->is_sticker() : true; bool pack_is_emoji = pack.pack ? pack.pack->is_emoji() : true; bool pack_matches = @@ -3921,6 +3923,7 @@ Cache::getImagePacks(const std::string &room_id, std::optional stickers) info.source_room = source_room; info.state_key = state_key; info.pack.pack = pack.pack; + info.from_space = from_space; for (const auto &img : pack.images) { if (stickers.has_value() && @@ -3942,7 +3945,7 @@ Cache::getImagePacks(const std::string &room_id, std::optional stickers) auto tmp = std::get_if>(&*accountpack); if (tmp) - addPack(tmp->content, "", ""); + addPack(tmp->content, "", "", false); } // packs from rooms, that were enabled globally @@ -3959,19 +3962,39 @@ Cache::getImagePacks(const std::string &room_id, std::optional stickers) (void)d; if (auto pack = getStateEvent(txn, room_id2, state_id)) - addPack(pack->content, room_id2, state_id); + addPack(pack->content, room_id2, state_id, false); } } } } - // packs from current room - if (auto pack = getStateEvent(txn, room_id)) { - addPack(pack->content, room_id, ""); - } - for (const auto &pack : getStateEventsWithType(txn, room_id)) { - addPack(pack.content, room_id, pack.state_key); - } + std::function addRoomAndCanonicalParents; + std::unordered_set visitedRooms; + addRoomAndCanonicalParents = + [this, &addRoomAndCanonicalParents, &addPack, &visitedRooms, &txn, &room_id]( + const std::string ¤t_room) { + if (visitedRooms.count(current_room)) + return; + else + visitedRooms.insert(current_room); + + if (auto pack = getStateEvent(txn, current_room)) { + addPack(pack->content, current_room, "", current_room != room_id); + } + for (const auto &pack : + getStateEventsWithType(txn, current_room)) { + addPack(pack.content, current_room, pack.state_key, current_room != room_id); + } + + for (const auto &parent : + getStateEventsWithType(txn, current_room)) { + if (parent.content.canonical && parent.content.via && !parent.content.via->empty()) + addRoomAndCanonicalParents(parent.state_key); + } + }; + + // packs from current room and then iterate canonical space parents + addRoomAndCanonicalParents(room_id); return infos; } diff --git a/src/CacheStructs.h b/src/CacheStructs.h index 43055145..459ced5a 100644 --- a/src/CacheStructs.h +++ b/src/CacheStructs.h @@ -126,4 +126,5 @@ struct ImagePackInfo mtx::events::msc2545::ImagePack pack; std::string source_room; std::string state_key; + bool from_space = false; }; diff --git a/src/ImagePackListModel.cpp b/src/ImagePackListModel.cpp index 6ce6306e..fac8f10f 100644 --- a/src/ImagePackListModel.cpp +++ b/src/ImagePackListModel.cpp @@ -36,6 +36,7 @@ ImagePackListModel::roleNames() const {Roles::AvatarUrl, "avatarUrl"}, {Roles::FromAccountData, "fromAccountData"}, {Roles::FromCurrentRoom, "fromCurrentRoom"}, + {Roles::FromSpace, "fromSpace"}, {Roles::StateKey, "statekey"}, {Roles::RoomId, "roomid"}, }; @@ -55,6 +56,8 @@ ImagePackListModel::data(const QModelIndex &index, int role) const return pack->roomid().isEmpty(); case Roles::FromCurrentRoom: return pack->roomid().toStdString() == this->room_id; + case Roles::FromSpace: + return pack->fromSpace(); case Roles::StateKey: return pack->statekey(); case Roles::RoomId: diff --git a/src/ImagePackListModel.h b/src/ImagePackListModel.h index 43fbcdfb..2e288094 100644 --- a/src/ImagePackListModel.h +++ b/src/ImagePackListModel.h @@ -21,6 +21,7 @@ public: AvatarUrl, FromAccountData, FromCurrentRoom, + FromSpace, StateKey, RoomId, }; diff --git a/src/SingleImagePackModel.cpp b/src/SingleImagePackModel.cpp index c7f01fad..02c9a3ce 100644 --- a/src/SingleImagePackModel.cpp +++ b/src/SingleImagePackModel.cpp @@ -26,6 +26,7 @@ SingleImagePackModel::SingleImagePackModel(ImagePackInfo pack_, QObject *parent) , statekey_(std::move(pack_.state_key)) , old_statekey_(statekey_) , pack(std::move(pack_.pack)) + , fromSpace_(pack_.from_space) { [[maybe_unused]] static auto imageInfoType = qRegisterMetaType(); diff --git a/src/SingleImagePackModel.h b/src/SingleImagePackModel.h index b732dcac..de2e4dea 100644 --- a/src/SingleImagePackModel.h +++ b/src/SingleImagePackModel.h @@ -18,6 +18,7 @@ class SingleImagePackModel : public QAbstractListModel Q_OBJECT Q_PROPERTY(QString roomid READ roomid CONSTANT) + Q_PROPERTY(bool fromSpace READ fromSpace CONSTANT) Q_PROPERTY(QString statekey READ statekey WRITE setStatekey NOTIFY statekeyChanged) Q_PROPERTY(QString attribution READ attribution WRITE setAttribution NOTIFY attributionChanged) Q_PROPERTY(QString packname READ packname WRITE setPackname NOTIFY packnameChanged) @@ -47,6 +48,7 @@ public: bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; QString roomid() const { return QString::fromStdString(roomid_); } + bool fromSpace() const { return fromSpace_; } QString statekey() const { return QString::fromStdString(statekey_); } QString packname() const { return QString::fromStdString(pack.pack->display_name); } QString attribution() const { return QString::fromStdString(pack.pack->attribution); } @@ -91,4 +93,6 @@ private: mtx::events::msc2545::ImagePack pack; std::vector shortcodes; + + bool fromSpace_ = false; };