File indexing completed on 2024-05-12 05:04:13

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