File indexing completed on 2024-05-05 05:01:24

0001 // SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
0002 // SPDX-License-Identifier: LGPL-2.0-or-later
0003 
0004 #include "notificationsmodel.h"
0005 
0006 #include <Quotient/connection.h>
0007 #include <Quotient/events/event.h>
0008 #include <Quotient/uri.h>
0009 
0010 #include "eventhandler.h"
0011 #include "neochatroom.h"
0012 
0013 using namespace Quotient;
0014 
0015 NotificationsModel::NotificationsModel(QObject *parent)
0016     : QAbstractListModel(parent)
0017 {
0018 }
0019 
0020 int NotificationsModel::rowCount(const QModelIndex &parent) const
0021 {
0022     Q_UNUSED(parent)
0023     return m_notifications.count();
0024 }
0025 
0026 QVariant NotificationsModel::data(const QModelIndex &index, int role) const
0027 {
0028     auto row = index.row();
0029     if (row < 0 || row >= m_notifications.count()) {
0030         return {};
0031     }
0032     if (role == TextRole) {
0033         return m_notifications[row].text;
0034     }
0035     if (role == RoomIdRole) {
0036         return m_notifications[row].roomId;
0037     }
0038     if (role == AuthorName) {
0039         return m_notifications[row].authorName;
0040     }
0041     if (role == AuthorAvatar) {
0042         return m_notifications[row].authorAvatar;
0043     }
0044     if (role == RoomRole) {
0045         return QVariant::fromValue(m_connection->room(m_notifications[row].roomId));
0046     }
0047     if (role == EventIdRole) {
0048         return m_notifications[row].eventId;
0049     }
0050     if (role == RoomDisplayNameRole) {
0051         return m_notifications[row].roomDisplayName;
0052     }
0053     if (role == UriRole) {
0054         return Uri(m_notifications[row].roomId.toLatin1(), m_notifications[row].eventId.toLatin1()).toUrl();
0055     }
0056     return {};
0057 }
0058 
0059 QHash<int, QByteArray> NotificationsModel::roleNames() const
0060 {
0061     return {
0062         {TextRole, "text"},
0063         {RoomIdRole, "roomId"},
0064         {AuthorName, "authorName"},
0065         {AuthorAvatar, "authorAvatar"},
0066         {RoomRole, "room"},
0067         {EventIdRole, "eventId"},
0068         {RoomDisplayNameRole, "roomDisplayName"},
0069         {UriRole, "uri"},
0070     };
0071 }
0072 
0073 NeoChatConnection *NotificationsModel::connection() const
0074 {
0075     return m_connection;
0076 }
0077 
0078 void NotificationsModel::setConnection(NeoChatConnection *connection)
0079 {
0080     if (m_connection) {
0081         // disconnect things...
0082     }
0083     if (!connection) {
0084         return;
0085     }
0086     m_connection = connection;
0087     Q_EMIT connectionChanged();
0088     connect(connection, &Connection::syncDone, this, [this]() {
0089         loadData();
0090     });
0091     loadData();
0092 }
0093 
0094 void NotificationsModel::loadData()
0095 {
0096     Q_ASSERT(m_connection);
0097     if (m_job || (m_notifications.size() && m_nextToken.isEmpty())) {
0098         return;
0099     }
0100     m_job = m_connection->callApi<GetNotificationsJob>(m_nextToken);
0101     Q_EMIT loadingChanged();
0102     connect(m_job, &BaseJob::finished, this, [this]() {
0103         m_nextToken = m_job->nextToken();
0104         Q_EMIT nextTokenChanged();
0105         for (const auto &notification : m_job->notifications()) {
0106             if (std::any_of(notification.actions.constBegin(), notification.actions.constEnd(), [](const QVariant &it) {
0107                     if (it.canConvert<QVariantMap>()) {
0108                         auto map = it.toMap();
0109                         if (map["set_tweak"_ls] == "highlight"_ls) {
0110                             return true;
0111                         }
0112                     }
0113                     return false;
0114                 })) {
0115                 const auto &authorId = notification.event->fullJson()["sender"_ls].toString();
0116                 const auto &room = m_connection->room(notification.roomId);
0117                 if (!room) {
0118                     continue;
0119                 }
0120                 auto u = room->memberAvatarUrl(authorId);
0121                 auto avatar = u.isEmpty() ? QUrl() : connection()->makeMediaUrl(u);
0122                 const auto &authorAvatar = avatar.isValid() && avatar.scheme() == QStringLiteral("mxc") ? avatar : QUrl();
0123 
0124                 const auto &roomEvent = eventCast<const RoomEvent>(notification.event.get());
0125                 EventHandler eventHandler(dynamic_cast<NeoChatRoom *>(room), roomEvent);
0126                 beginInsertRows({}, m_notifications.length(), m_notifications.length());
0127                 m_notifications += Notification{
0128                     .roomId = notification.roomId,
0129                     .text = room->htmlSafeMemberName(authorId) + (roomEvent->is<StateEvent>() ? QStringLiteral(" ") : QStringLiteral(": "))
0130                         + eventHandler.getPlainBody(true),
0131                     .authorName = room->htmlSafeMemberName(authorId),
0132                     .authorAvatar = authorAvatar,
0133                     .eventId = roomEvent->id(),
0134                     .roomDisplayName = room->displayName(),
0135                 };
0136                 endInsertRows();
0137             }
0138         }
0139         m_job = nullptr;
0140         Q_EMIT loadingChanged();
0141     });
0142 }
0143 
0144 bool NotificationsModel::canFetchMore(const QModelIndex &parent) const
0145 {
0146     Q_UNUSED(parent);
0147     return !m_nextToken.isEmpty();
0148 }
0149 
0150 void NotificationsModel::fetchMore(const QModelIndex &parent)
0151 {
0152     Q_UNUSED(parent);
0153     loadData();
0154 }
0155 
0156 bool NotificationsModel::loading() const
0157 {
0158     return m_job;
0159 }
0160 
0161 QString NotificationsModel::nextToken() const
0162 {
0163     return m_nextToken;
0164 }