File indexing completed on 2024-05-12 16:28:08

0001 // SPDX-FileCopyrightText: 2022 Carl Schwan <carlschwan@kde.org>
0002 // SPDX-License-Identifier: LGPL-2.0-or-later
0003 
0004 #include "conversationmodel.h"
0005 
0006 #include "account/abstractaccount.h"
0007 #include "account/accountmanager.h"
0008 #include "account/identity.h"
0009 #include <KLocalizedString>
0010 #include <QTextDocumentFragment>
0011 #include <algorithm>
0012 #include <qvariant.h>
0013 
0014 ConversationModel::ConversationModel(QObject *parent)
0015     : AbstractTimelineModel(parent)
0016 {
0017     if (AccountManager::instance().selectedAccount()) {
0018         fetchConversation(AccountManager::instance().selectedAccount());
0019     }
0020     connect(&AccountManager::instance(), &AccountManager::accountSelected, this, [this](AbstractAccount *account) {
0021         fetchConversation(account);
0022     });
0023 }
0024 
0025 ConversationModel::~ConversationModel() = default;
0026 
0027 QHash<int, QByteArray> ConversationModel::roleNames() const
0028 {
0029     auto roles = AbstractTimelineModel::roleNames();
0030     roles.insert(UnreadRole, QByteArrayLiteral("unread"));
0031     roles.insert(ConversationIdRole, QByteArrayLiteral("conversationId"));
0032     return roles;
0033 }
0034 
0035 int ConversationModel::rowCount(const QModelIndex &parent) const
0036 {
0037     Q_UNUSED(parent);
0038     return m_conversations.count();
0039 }
0040 
0041 QVariant ConversationModel::data(const QModelIndex &index, int role) const
0042 {
0043     const auto row = index.row();
0044     const auto lastPost = m_conversations[row].lastPost;
0045     const auto &identities = m_conversations[row].accounts;
0046     const auto &firstIdentity = identities[0];
0047 
0048     switch (role) {
0049     case AuthorIdentityRole:
0050         return QVariant::fromValue<Identity *>(firstIdentity.get());
0051     case ConversationIdRole:
0052         return m_conversations[row].id;
0053     case UnreadRole:
0054         return m_conversations[row].unread;
0055     case ContentRole:
0056         return QTextDocumentFragment::fromHtml(lastPost->content()).toPlainText();
0057     case ConversationAuthorsRole:
0058         if (identities.count() == 0) {
0059             return i18n("Empty conversation");
0060         } else if (identities.count() == 1) {
0061             return firstIdentity->displayNameHtml();
0062         } else if (identities.count() == 2) {
0063             return i18n("%1 and %2", firstIdentity->displayNameHtml(), identities[2]->displayNameHtml());
0064         } else {
0065             return i18np("%2 and one other", "%2 and %1 others", identities.count() - 1, firstIdentity->displayNameHtml());
0066         }
0067     default:
0068         return postData(lastPost, role);
0069     }
0070 }
0071 
0072 void ConversationModel::fetchConversation(AbstractAccount *account)
0073 {
0074     setLoading(true);
0075 
0076     account->get(account->apiUrl("/api/v1/conversations"), true, this, [account, this](QNetworkReply *reply) {
0077         beginResetModel();
0078         m_conversations.clear();
0079         const auto conversationArray = QJsonDocument::fromJson(reply->readAll()).array();
0080         for (const auto &conversation : conversationArray) {
0081             const auto obj = conversation.toObject();
0082             const auto accountsArray = obj["accounts"].toArray();
0083             QList<std::shared_ptr<Identity>> accounts;
0084             std::transform(
0085                 accountsArray.cbegin(),
0086                 accountsArray.cend(),
0087                 std::back_inserter(accounts),
0088                 [account](const QJsonValue &value) -> auto{
0089                     const auto accountObj = value.toObject();
0090                     return account->identityLookup(accountObj["id"].toString(), accountObj);
0091                 });
0092             m_conversations.append(Conversation{
0093                 accounts,
0094                 new Post(account, obj["last_status"].toObject(), this),
0095                 obj["unread"].toBool(),
0096                 obj["id"].toString(),
0097             });
0098         }
0099         setLoading(false);
0100         endResetModel();
0101     });
0102 }
0103 
0104 void ConversationModel::markAsRead(const QString &id)
0105 {
0106     auto account = AccountManager::instance().selectedAccount();
0107 
0108     account->post(account->apiUrl(QString("/api/v1/conversations/%1/read").arg(id)), QJsonDocument(), true, this, [id, this](QNetworkReply *reply) {
0109         const auto conversationObj = QJsonDocument::fromJson(reply->readAll()).object();
0110         int i = 0;
0111         for (auto &conversation : m_conversations) {
0112             if (conversation.id == id) {
0113                 conversation.unread = false;
0114                 Q_EMIT dataChanged(index(i, 0), index(i, 0), {UnreadRole});
0115                 break;
0116             }
0117             i++;
0118         }
0119     });
0120 }