File indexing completed on 2024-05-12 16:25:04

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"] = QJsonObject{
0086             {"display_name", m_showStickers ? i18nc("As in 'The user's own Stickers'", "Own Stickers") : i18nc("As in 'The user's own emojis", "Own Emojis")},
0087         };
0088         const auto &content = ImagePackEventContent(json);
0089         if (!content.images.isEmpty()) {
0090             m_events += ImagePackEventContent(json);
0091         }
0092     }
0093 
0094     // Load emoticons from the saved rooms
0095     const auto &accountData = m_room->connection()->accountData("im.ponies.emote_rooms"_ls);
0096     if (accountData) {
0097         const auto &rooms = accountData->contentJson()["rooms"_ls].toObject();
0098         for (const auto &roomId : rooms.keys()) {
0099             if (roomId == m_room->id()) {
0100                 continue;
0101             }
0102             auto packs = rooms[roomId].toObject();
0103             const auto &stickerRoom = m_room->connection()->room(roomId);
0104             for (const auto &packKey : packs.keys()) {
0105                 if (const auto &pack = stickerRoom->currentState().get<ImagePackEvent>(packKey)) {
0106                     const auto packContent = pack->content();
0107                     if ((!packContent.pack || !packContent.pack->usage || (packContent.pack->usage->contains("emoticon") && showEmoticons())
0108                          || (packContent.pack->usage->contains("sticker") && showStickers()))
0109                         && !packContent.images.isEmpty()) {
0110                         m_events += packContent;
0111                     }
0112                 }
0113             }
0114         }
0115     }
0116 
0117     // Load emoticons from the current room
0118     auto events = m_room->currentState().eventsOfType("im.ponies.room_emotes");
0119     for (const auto &event : events) {
0120         auto packContent = eventCast<const ImagePackEvent>(event)->content();
0121         if (packContent.pack.has_value()) {
0122             if (!packContent.pack->usage || (packContent.pack->usage->contains("emoticon") && showEmoticons())
0123                 || (packContent.pack->usage->contains("sticker") && showStickers())) {
0124                 m_events += packContent;
0125             }
0126         }
0127     }
0128     Q_EMIT imagesLoaded();
0129     endResetModel();
0130 }
0131 
0132 bool ImagePacksModel::showStickers() const
0133 {
0134     return m_showStickers;
0135 }
0136 
0137 void ImagePacksModel::setShowStickers(bool showStickers)
0138 {
0139     m_showStickers = showStickers;
0140     Q_EMIT showStickersChanged();
0141 }
0142 
0143 bool ImagePacksModel::showEmoticons() const
0144 {
0145     return m_showEmoticons;
0146 }
0147 
0148 void ImagePacksModel::setShowEmoticons(bool showEmoticons)
0149 {
0150     m_showEmoticons = showEmoticons;
0151     Q_EMIT showEmoticonsChanged();
0152 }
0153 QVector<Quotient::ImagePackEventContent::ImagePackImage> ImagePacksModel::images(int index)
0154 {
0155     if (index < 0 || index >= m_events.size()) {
0156         return {};
0157     }
0158     return m_events[index].images;
0159 }
0160 
0161 #include "moc_imagepacksmodel.cpp"