File indexing completed on 2024-12-08 07:33:44

0001 // SPDX-FileCopyrightText: 2021 Tobias Fella <tobias.fella@kde.org>
0002 // SPDX-License-Identifier: LGPL-2.0-or-later
0003 
0004 #include "imagepacksmodel.h"
0005 #include "neochatroom.h"
0006 
0007 #include <KLocalizedString>
0008 
0009 using namespace Quotient;
0010 
0011 ImagePacksModel::ImagePacksModel(QObject *parent)
0012     : QAbstractListModel(parent)
0013 {
0014 }
0015 
0016 int ImagePacksModel::rowCount(const QModelIndex &index) const
0017 {
0018     Q_UNUSED(index);
0019     return m_events.count();
0020 }
0021 
0022 QVariant ImagePacksModel::data(const QModelIndex &index, int role) const
0023 {
0024     const auto row = index.row();
0025     if (row < 0 || row >= m_events.size()) {
0026         return {};
0027     }
0028     const auto &event = m_events[row];
0029     if (role == DisplayNameRole) {
0030         if (event.pack->displayName) {
0031             return *event.pack->displayName;
0032         }
0033     }
0034     if (role == AvatarUrlRole) {
0035         if (event.pack->avatarUrl) {
0036             return m_room->connection()->makeMediaUrl(*event.pack->avatarUrl);
0037         } else if (!event.images.empty()) {
0038             return m_room->connection()->makeMediaUrl(event.images[0].url);
0039         }
0040     }
0041     return {};
0042 }
0043 
0044 QHash<int, QByteArray> ImagePacksModel::roleNames() const
0045 {
0046     return {
0047         {DisplayNameRole, "displayName"},
0048         {AvatarUrlRole, "avatarUrl"},
0049         {AttributionRole, "attribution"},
0050         {IdRole, "id"},
0051     };
0052 }
0053 
0054 NeoChatRoom *ImagePacksModel::room() const
0055 {
0056     return m_room;
0057 }
0058 
0059 void ImagePacksModel::setRoom(NeoChatRoom *room)
0060 {
0061     if (m_room) {
0062         disconnect(m_room, nullptr, this, nullptr);
0063         disconnect(m_room->connection(), nullptr, this, nullptr);
0064     }
0065     m_room = room;
0066 
0067     connect(m_room->connection(), &Connection::accountDataChanged, this, [this](const QString &type) {
0068         if (type == "im.ponies.user_emotes"_ls) {
0069             reloadImages();
0070         }
0071     });
0072     // TODO listen to packs changing
0073     reloadImages();
0074     Q_EMIT roomChanged();
0075 }
0076 
0077 void ImagePacksModel::reloadImages()
0078 {
0079     beginResetModel();
0080     m_events.clear();
0081 
0082     // Load emoticons from the account data
0083     if (m_room->connection()->hasAccountData("im.ponies.user_emotes"_ls)) {
0084         auto json = m_room->connection()->accountData("im.ponies.user_emotes"_ls)->contentJson();
0085         json["pack"_ls] = QJsonObject{
0086             {"display_name"_ls,
0087              m_showStickers ? i18nc("As in 'The user's own Stickers'", "Own Stickers") : i18nc("As in 'The user's own emojis", "Own Emojis")},
0088         };
0089         const auto &content = ImagePackEventContent(json);
0090         if (!content.images.isEmpty()) {
0091             m_events += ImagePackEventContent(json);
0092         }
0093     }
0094 
0095     // Load emoticons from the saved rooms
0096     const auto &accountData = m_room->connection()->accountData("im.ponies.emote_rooms"_ls);
0097     if (accountData) {
0098         const auto &rooms = accountData->contentJson()["rooms"_ls].toObject();
0099         for (const auto &roomId : rooms.keys()) {
0100             if (roomId == m_room->id()) {
0101                 continue;
0102             }
0103             auto packs = rooms[roomId].toObject();
0104             const auto &stickerRoom = m_room->connection()->room(roomId);
0105             if (!stickerRoom) {
0106                 continue;
0107             }
0108             for (const auto &packKey : packs.keys()) {
0109                 if (const auto &pack = stickerRoom->currentState().get<ImagePackEvent>(packKey)) {
0110                     const auto packContent = pack->content();
0111                     if ((!packContent.pack || !packContent.pack->usage || (packContent.pack->usage->contains("emoticon"_ls) && showEmoticons())
0112                          || (packContent.pack->usage->contains("sticker"_ls) && showStickers()))
0113                         && !packContent.images.isEmpty()) {
0114                         m_events += packContent;
0115                     }
0116                 }
0117             }
0118         }
0119     }
0120 
0121     // Load emoticons from the current room
0122     auto events = m_room->currentState().eventsOfType("im.ponies.room_emotes"_ls);
0123     for (const auto &event : events) {
0124         auto packContent = eventCast<const ImagePackEvent>(event)->content();
0125         if (packContent.pack.has_value()) {
0126             if (!packContent.pack->usage || (packContent.pack->usage->contains("emoticon"_ls) && showEmoticons())
0127                 || (packContent.pack->usage->contains("sticker"_ls) && showStickers())) {
0128                 m_events += packContent;
0129             }
0130         }
0131     }
0132     Q_EMIT imagesLoaded();
0133     endResetModel();
0134 }
0135 
0136 bool ImagePacksModel::showStickers() const
0137 {
0138     return m_showStickers;
0139 }
0140 
0141 void ImagePacksModel::setShowStickers(bool showStickers)
0142 {
0143     m_showStickers = showStickers;
0144     Q_EMIT showStickersChanged();
0145 }
0146 
0147 bool ImagePacksModel::showEmoticons() const
0148 {
0149     return m_showEmoticons;
0150 }
0151 
0152 void ImagePacksModel::setShowEmoticons(bool showEmoticons)
0153 {
0154     m_showEmoticons = showEmoticons;
0155     Q_EMIT showEmoticonsChanged();
0156 }
0157 QList<Quotient::ImagePackEventContent::ImagePackImage> ImagePacksModel::images(int index)
0158 {
0159     if (index < 0 || index >= m_events.size()) {
0160         return {};
0161     }
0162     return m_events[index].images;
0163 }
0164 
0165 #include "moc_imagepacksmodel.cpp"