File indexing completed on 2024-12-08 07:33:45
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 ¬ification : 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; 0126 eventHandler.setRoom(dynamic_cast<NeoChatRoom *>(room)); 0127 eventHandler.setEvent(roomEvent); 0128 beginInsertRows({}, m_notifications.length(), m_notifications.length()); 0129 m_notifications += Notification{ 0130 .roomId = notification.roomId, 0131 .text = room->htmlSafeMemberName(authorId) + (roomEvent->is<StateEvent>() ? QStringLiteral(" ") : QStringLiteral(": ")) 0132 + eventHandler.getPlainBody(true), 0133 .authorName = room->htmlSafeMemberName(authorId), 0134 .authorAvatar = authorAvatar, 0135 .eventId = roomEvent->id(), 0136 .roomDisplayName = room->displayName(), 0137 }; 0138 endInsertRows(); 0139 } 0140 } 0141 m_job = nullptr; 0142 Q_EMIT loadingChanged(); 0143 }); 0144 } 0145 0146 bool NotificationsModel::canFetchMore(const QModelIndex &parent) const 0147 { 0148 Q_UNUSED(parent); 0149 return !m_nextToken.isEmpty(); 0150 } 0151 0152 void NotificationsModel::fetchMore(const QModelIndex &parent) 0153 { 0154 Q_UNUSED(parent); 0155 loadData(); 0156 } 0157 0158 bool NotificationsModel::loading() const 0159 { 0160 return m_job; 0161 } 0162 0163 QString NotificationsModel::nextToken() const 0164 { 0165 return m_nextToken; 0166 }