// SPDX-FileCopyrightText: 2023 Tobias Fella // SPDX-License-Identifier: LGPL-2.0-or-later #include "notificationsmodel.h" #include #include #include "eventhandler.h" #include "neochatroom.h" using namespace Quotient; NotificationsModel::NotificationsModel(QObject *parent) : QAbstractListModel(parent) { } int NotificationsModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent) return m_notifications.count(); } QVariant NotificationsModel::data(const QModelIndex &index, int role) const { auto row = index.row(); if (row < 0 || row >= m_notifications.count()) { return {}; } if (role == TextRole) { return m_notifications[row].text; } if (role == RoomIdRole) { return m_notifications[row].roomId; } if (role == AuthorName) { return m_notifications[row].authorName; } if (role == AuthorAvatar) { return m_notifications[row].authorAvatar; } if (role == RoomRole) { return QVariant::fromValue(m_connection->room(m_notifications[row].roomId)); } if (role == EventIdRole) { return m_notifications[row].eventId; } if (role == RoomDisplayNameRole) { return m_notifications[row].roomDisplayName; } if (role == UriRole) { return Uri(m_notifications[row].roomId.toLatin1(), m_notifications[row].eventId.toLatin1()).toUrl(); } return {}; } QHash NotificationsModel::roleNames() const { return { {TextRole, "text"}, {RoomIdRole, "roomId"}, {AuthorName, "authorName"}, {AuthorAvatar, "authorAvatar"}, {RoomRole, "room"}, {EventIdRole, "eventId"}, {RoomDisplayNameRole, "roomDisplayName"}, {UriRole, "uri"}, }; } NeoChatConnection *NotificationsModel::connection() const { return m_connection; } void NotificationsModel::setConnection(NeoChatConnection *connection) { if (m_connection) { // disconnect things... } if (!connection) { return; } m_connection = connection; Q_EMIT connectionChanged(); connect(connection, &Connection::syncDone, this, [this]() { loadData(); }); loadData(); } void NotificationsModel::loadData() { Q_ASSERT(m_connection); if (m_job || (m_notifications.size() && m_nextToken.isEmpty())) { return; } m_job = m_connection->callApi(m_nextToken); Q_EMIT loadingChanged(); connect(m_job, &BaseJob::finished, this, [this]() { m_nextToken = m_job->nextToken(); Q_EMIT nextTokenChanged(); for (const auto ¬ification : m_job->notifications()) { if (std::any_of(notification.actions.constBegin(), notification.actions.constEnd(), [](const QVariant &it) { if (it.canConvert()) { auto map = it.toMap(); if (map["set_tweak"_L1] == "highlight"_L1) { return true; } } return false; })) { const auto &authorId = notification.event->fullJson()["sender"_L1].toString(); const auto &room = m_connection->room(notification.roomId); if (!room) { continue; } auto u = room->member(authorId).avatarUrl(); auto avatar = u.isEmpty() ? QUrl() : connection()->makeMediaUrl(u); const auto &authorAvatar = avatar.isValid() && avatar.scheme() == u"mxc"_s ? avatar : QUrl(); const auto &roomEvent = eventCast(notification.event.get()); if (!roomEvent) { continue; } beginInsertRows({}, m_notifications.length(), m_notifications.length()); m_notifications += Notification{ .roomId = notification.roomId, .text = room->member(authorId).htmlSafeDisplayName() + (roomEvent->is() ? u" "_s : u": "_s) + EventHandler::plainBody(dynamic_cast(room), roomEvent, true), .authorName = room->member(authorId).htmlSafeDisplayName(), .authorAvatar = authorAvatar, .eventId = roomEvent->id(), .roomDisplayName = room->displayName(), }; endInsertRows(); } } m_job = nullptr; Q_EMIT loadingChanged(); }); } bool NotificationsModel::canFetchMore(const QModelIndex &parent) const { Q_UNUSED(parent); return !m_nextToken.isEmpty(); } void NotificationsModel::fetchMore(const QModelIndex &parent) { Q_UNUSED(parent); loadData(); } bool NotificationsModel::loading() const { return m_job; } QString NotificationsModel::nextToken() const { return m_nextToken; } #include "moc_notificationsmodel.cpp"