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

0001 // SPDX-FileCopyrightText: 2023 Shubham Arora <shubhamarora@protonmail.com>
0002 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0003 
0004 #include "tagsmodel.h"
0005 
0006 #include <KLocalizedString>
0007 
0008 TagsModel::TagsModel(QObject *parent)
0009     : AbstractListModel(parent)
0010 {
0011     connect(this, &AbstractListModel::nameChanged, this, &TagsModel::onNameChanged);
0012 }
0013 
0014 void TagsModel::onNameChanged()
0015 {
0016     fillTimeline();
0017 }
0018 
0019 QString TagsModel::displayName() const
0020 {
0021     return i18n("Trending");
0022 }
0023 
0024 void TagsModel::fetchMore(const QModelIndex &parent)
0025 {
0026     Q_UNUSED(parent);
0027     if (shouldLoadMore()) {
0028         fillTimeline();
0029     } else {
0030         setShouldLoadMore(true);
0031     }
0032 }
0033 
0034 bool TagsModel::canFetchMore(const QModelIndex &parent) const
0035 {
0036     Q_UNUSED(parent);
0037     return !m_next.isEmpty();
0038 }
0039 
0040 void TagsModel::fillTimeline(const QString &fromId)
0041 {
0042     Q_UNUSED(fromId);
0043 
0044     if (!account() || loading() || name() != QStringLiteral("trending")) {
0045         return;
0046     }
0047 
0048     QUrlQuery q;
0049     q.addQueryItem(QStringLiteral("limit"), QStringLiteral("20"));
0050     QUrl uri;
0051     if (m_next.isEmpty()) {
0052         if (name() == QStringLiteral("trending")) {
0053             uri = account()->apiUrl(QStringLiteral("/api/v1/trends/tags"));
0054             uri.setQuery(q);
0055         }
0056     } else {
0057         uri = m_next;
0058     }
0059 
0060     setLoading(true);
0061     account()->get(
0062         uri,
0063         false,
0064         this,
0065         [this, uri](QNetworkReply *reply) {
0066             const auto data = reply->readAll();
0067             const auto doc = QJsonDocument::fromJson(data);
0068             if (!doc.isArray()) {
0069                 return;
0070             }
0071             static QRegularExpression re(QStringLiteral("<(.*)>; rel=\"next\""));
0072             const auto next = reply->rawHeader(QByteArrayLiteral("Link"));
0073             const auto match = re.match(QString::fromUtf8(next));
0074             m_next = QUrl::fromUserInput(match.captured(1));
0075             const auto values = doc.array();
0076 
0077             QList<Tag> tags;
0078             std::transform(values.cbegin(), values.cend(), std::back_inserter(tags), [](const QJsonValue &value) {
0079                 return Tag(value.toObject());
0080             });
0081 
0082             beginInsertRows({}, m_tags.size(), m_tags.size() + tags.size() - 1);
0083             m_tags += tags;
0084             endInsertRows();
0085             setLoading(false);
0086         },
0087         [this](QNetworkReply *reply) {
0088             Q_UNUSED(reply);
0089             setLoading(false);
0090         });
0091 }
0092 
0093 QHash<int, QByteArray> TagsModel::roleNames() const
0094 {
0095     return {
0096         {CustomRoles::NameRole, "name"},
0097         {CustomRoles::UrlRole, "url"},
0098         {CustomRoles::HistoryRole, "history"},
0099     };
0100 }
0101 
0102 QVariant TagsModel::data(const QModelIndex &index, int role) const
0103 {
0104     Q_ASSERT(checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid));
0105 
0106     switch (role) {
0107     case CustomRoles::NameRole:
0108         return m_tags[index.row()].name();
0109     case CustomRoles::UrlRole:
0110         return m_tags[index.row()].url();
0111     case CustomRoles::HistoryRole:
0112         return QVariant::fromValue<QList<History>>(m_tags[index.row()].history());
0113     default:
0114         return {};
0115     }
0116 }
0117 
0118 int TagsModel::rowCount(const QModelIndex &parent) const
0119 {
0120     Q_UNUSED(parent)
0121     return m_tags.size();
0122 }
0123 
0124 #include "moc_tagsmodel.cpp"