diff --git a/resources/graphics/misc/freshrss.png b/resources/graphics/misc/freshrss.png new file mode 100644 index 000000000..c090eff04 Binary files /dev/null and b/resources/graphics/misc/freshrss.png differ diff --git a/resources/graphics/misc/theoldreader.png b/resources/graphics/misc/theoldreader.png new file mode 100644 index 000000000..6863efd89 Binary files /dev/null and b/resources/graphics/misc/theoldreader.png differ diff --git a/resources/rssguard.qrc b/resources/rssguard.qrc index 3c58b674a..60a4f36fd 100755 --- a/resources/rssguard.qrc +++ b/resources/rssguard.qrc @@ -16,11 +16,13 @@ graphics/misc/adblock.png graphics/misc/adblock-disabled.png + graphics/misc/freshrss.png graphics/misc/gmail.png graphics/misc/google.png graphics/misc/image-placeholder.png graphics/misc/inoreader.png graphics/misc/nextcloud.png + graphics/misc/theoldreader.png graphics/misc/tt-rss.png graphics/misc/flags/cs.png diff --git a/resources/scripts/7za b/resources/scripts/7za index 47f412575..9c10723bf 160000 --- a/resources/scripts/7za +++ b/resources/scripts/7za @@ -1 +1 @@ -Subproject commit 47f4125753452eff8800dbd6600c5a05540b15d9 +Subproject commit 9c10723bfbaf6cb85107d6ee16e0324e9e487749 diff --git a/src/librssguard/network-web/networkfactory.cpp b/src/librssguard/network-web/networkfactory.cpp index 57a6221d4..2e84624a0 100644 --- a/src/librssguard/network-web/networkfactory.cpp +++ b/src/librssguard/network-web/networkfactory.cpp @@ -137,8 +137,9 @@ QString NetworkFactory::networkErrorText(QNetworkReply::NetworkError error_code) } } -QNetworkReply::NetworkError NetworkFactory::downloadIcon(const QList& urls, int timeout, QIcon& output, const QNetworkProxy& custom_proxy) { - QNetworkReply::NetworkError network_result = QNetworkReply::UnknownNetworkError; +QNetworkReply::NetworkError NetworkFactory::downloadIcon(const QList& urls, int timeout, + QIcon& output, const QNetworkProxy& custom_proxy) { + QNetworkReply::NetworkError network_result = QNetworkReply::NetworkError::UnknownNetworkError; for (const QString& url : urls) { QByteArray icon_data; diff --git a/src/librssguard/services/greader/definitions.h b/src/librssguard/services/greader/definitions.h index 4249394ae..f7f75a923 100755 --- a/src/librssguard/services/greader/definitions.h +++ b/src/librssguard/services/greader/definitions.h @@ -23,6 +23,9 @@ #define GREADER_API_EDIT_TAG_BATCH 200 #define GREADER_API_ANY_LABEL "user/-/label" +// The Old Reader. +#define TOR_SPONSORED_STREAM_ID "tor/sponsored" + // FreshRSS. #define FRESHRSS_BASE_URL_PATH "api/greader.php/" diff --git a/src/librssguard/services/greader/greadernetwork.cpp b/src/librssguard/services/greader/greadernetwork.cpp index 98bc7b87e..cb709bc59 100755 --- a/src/librssguard/services/greader/greadernetwork.cpp +++ b/src/librssguard/services/greader/greadernetwork.cpp @@ -179,18 +179,42 @@ RootItem* GreaderNetwork::categoriesFeedsLabelsTree(bool obtain_icons, const QNe return nullptr; } - auto root = decodeTagsSubscriptions(output_labels, output_feeds, obtain_icons); - - return root; + return decodeTagsSubscriptions(output_labels, output_feeds, obtain_icons, proxy); } -RootItem* GreaderNetwork::decodeTagsSubscriptions(const QString& categories, const QString& feeds, bool obtain_icons) { +RootItem* GreaderNetwork::decodeTagsSubscriptions(const QString& categories, const QString& feeds, + bool obtain_icons, const QNetworkProxy& proxy) { auto* parent = new RootItem(); auto timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); - QJsonArray json = QJsonDocument::fromJson(categories.toUtf8()).object()["tags"].toArray(); QMap cats; QList lbls; + QJsonArray json; + if (m_service == GreaderServiceRoot::Service::Bazqux) { + // We need to process subscription list first and extract categories. + json = QJsonDocument::fromJson(feeds.toUtf8()).object()["subscriptions"].toArray(); + + for (const QJsonValue& feed : json) { + auto subscription = feed.toObject(); + + for (const QJsonValue& cat : subscription["categories"].toArray()) { + auto cat_obj = cat.toObject(); + auto cat_id = simplifyStreamId(cat_obj["id"].toString()); + + if (!cats.contains(cat_id)) { + auto* category = new Category(); + + category->setTitle(cat_id.mid(cat_id.lastIndexOf(QL1C('/')) + 1)); + category->setCustomId(cat_id); + + cats.insert(category->customId(), category); + parent->appendChild(category); + } + } + } + } + + json = QJsonDocument::fromJson(categories.toUtf8()).object()["tags"].toArray(); cats.insert(QString(), parent); for (const QJsonValue& obj : json) { @@ -218,6 +242,19 @@ RootItem* GreaderNetwork::decodeTagsSubscriptions(const QString& categories, con new_lbl->setCustomId(label_id); lbls.append(new_lbl); } + else if (m_service == GreaderServiceRoot::Service::Bazqux && + label_id.contains(QSL("/label/"))) { + label_id = simplifyStreamId(label_id); + + if (!cats.contains(label_id)) { + // This stream is not a category, it is label, bitches! + QString plain_name = QRegularExpression(".+\\/([^\\/]+)").match(label_id).captured(1); + auto* new_lbl = new Label(plain_name, TextFactory::generateColorFromText(label_id)); + + new_lbl->setCustomId(label_id); + lbls.append(new_lbl); + } + } } json = QJsonDocument::fromJson(feeds.toUtf8()).object()["subscriptions"].toArray(); @@ -230,11 +267,15 @@ RootItem* GreaderNetwork::decodeTagsSubscriptions(const QString& categories, con QString parent_label; QJsonArray assigned_categories = subscription["categories"].toArray(); + if (id.startsWith(TOR_SPONSORED_STREAM_ID)) { + continue; + } + for (const QJsonValue& cat : assigned_categories) { QString potential_id = cat.toObject()["id"].toString(); if (potential_id.contains(QSL("/label/"))) { - parent_label = potential_id; + parent_label = m_service == GreaderServiceRoot::Service::Bazqux ? simplifyStreamId(potential_id) : potential_id; break; } } @@ -248,7 +289,9 @@ RootItem* GreaderNetwork::decodeTagsSubscriptions(const QString& categories, con feed->setCustomId(id); if (obtain_icons) { - QString icon_url = subscription["iconUrl"].toString(); + QString icon_url = subscription.contains(QSL("iconUrl")) + ? subscription["iconUrl"].toString() + : subscription["htmlUrl"].toString(); if (!icon_url.isEmpty()) { QByteArray icon_data; @@ -257,15 +300,13 @@ RootItem* GreaderNetwork::decodeTagsSubscriptions(const QString& categories, con icon_url = QUrl(baseUrl()).scheme() + QSL(":") + icon_url; } - if (NetworkFactory::performNetworkOperation(icon_url, timeout, - {}, icon_data, - QNetworkAccessManager::Operation::GetOperation).first == - QNetworkReply::NetworkError::NoError) { - // Icon downloaded, set it up. - QPixmap icon_pixmap; + QIcon icon; - icon_pixmap.loadFromData(icon_data); - feed->setIcon(QIcon(icon_pixmap)); + if (NetworkFactory::downloadIcon({ icon_url }, + timeout, + icon, + proxy) == QNetworkReply::NetworkError::NoError) { + feed->setIcon(icon); } } } @@ -378,7 +419,7 @@ QString GreaderNetwork::serviceToString(GreaderServiceRoot::Service service) { return QSL("Bazqux"); case GreaderServiceRoot::Service::TheOldReader: - return QSL("TheOldReader"); + return QSL("The Old Reader"); default: return tr("Unknown service"); @@ -408,6 +449,10 @@ bool GreaderNetwork::ensureLogin(const QNetworkProxy& proxy, QNetworkReply::Netw return true; } +QString GreaderNetwork::simplifyStreamId(const QString& stream_id) const { + return QString(stream_id).replace(QRegularExpression("\\/\\d+\\/"), QSL("/-/")); +} + QList GreaderNetwork::decodeStreamContents(ServiceRoot* root, const QString& stream_json_data, const QString& stream_id) { diff --git a/src/librssguard/services/greader/greadernetwork.h b/src/librssguard/services/greader/greadernetwork.h index 5574082ba..a203cf55a 100755 --- a/src/librssguard/services/greader/greadernetwork.h +++ b/src/librssguard/services/greader/greadernetwork.h @@ -70,8 +70,9 @@ class GreaderNetwork : public QObject { // Make sure we are logged in and if we are not, return error. bool ensureLogin(const QNetworkProxy& proxy, QNetworkReply::NetworkError* output = nullptr); + QString simplifyStreamId(const QString& stream_id) const; QList decodeStreamContents(ServiceRoot* root, const QString& stream_json_data, const QString& stream_id); - RootItem* decodeTagsSubscriptions(const QString& categories, const QString& feeds, bool obtain_icons); + RootItem* decodeTagsSubscriptions(const QString& categories, const QString& feeds, bool obtain_icons, const QNetworkProxy& proxy); QString sanitizedBaseUrl() const; QString generateFullUrl(Operations operation) const; diff --git a/src/librssguard/services/greader/greaderserviceroot.cpp b/src/librssguard/services/greader/greaderserviceroot.cpp index 026b13a18..dc2022e0f 100755 --- a/src/librssguard/services/greader/greaderserviceroot.cpp +++ b/src/librssguard/services/greader/greaderserviceroot.cpp @@ -142,6 +142,20 @@ void GreaderServiceRoot::saveAllCachedData(bool ignore_errors) { void GreaderServiceRoot::updateTitle() { setTitle(QString("%1 (%2)").arg(m_network->username(), m_network->serviceToString(m_network->service()))); + + switch (m_network->service()) { + case Service::TheOldReader: + setIcon(qApp->icons()->miscIcon(QSL("theoldreader"))); + break; + + case Service::FreshRss: + setIcon(qApp->icons()->miscIcon(QSL("freshrss"))); + break; + + default: + setIcon(GreaderEntryPoint().icon()); + break; + } } void GreaderServiceRoot::saveAccountDataToDatabase(bool creating_new) {