From 72ab1a43b0b701ee36df654932148984262bc7d7 Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Thu, 22 Oct 2020 20:49:06 +0200 Subject: [PATCH] Obtain labels when sync-in for Inoreader #102. --- resources/scripts/uncrustify/uncrustify.cfg | 3 ++ .../services/abstract/cacheforserviceroot.cpp | 4 -- src/librssguard/services/abstract/label.cpp | 8 +-- src/librssguard/services/abstract/rootitem.h | 6 ++- .../services/inoreader/definitions.h | 2 +- .../inoreader/inoreaderserviceroot.cpp | 18 ++++++- .../network/inoreadernetworkfactory.cpp | 52 ++++++++++++++++++- .../network/inoreadernetworkfactory.h | 2 + .../services/tt-rss/ttrssserviceroot.cpp | 13 +++++ 9 files changed, 95 insertions(+), 13 deletions(-) diff --git a/resources/scripts/uncrustify/uncrustify.cfg b/resources/scripts/uncrustify/uncrustify.cfg index a33d9f3a5..3277a9f5d 100644 --- a/resources/scripts/uncrustify/uncrustify.cfg +++ b/resources/scripts/uncrustify/uncrustify.cfg @@ -95,6 +95,9 @@ sp_angle_shift = remove # ignore/add/remove/force # sp_angle_shift cannot remove the space without this option. sp_permit_cpp11_shift = true # false/true +sp_after_type_brace_init_lst_open = force +sp_before_type_brace_init_lst_close = force + ## Indents. # The number of columns to indent per level. diff --git a/src/librssguard/services/abstract/cacheforserviceroot.cpp b/src/librssguard/services/abstract/cacheforserviceroot.cpp index 2f9fb6d62..eed3cbd70 100644 --- a/src/librssguard/services/abstract/cacheforserviceroot.cpp +++ b/src/librssguard/services/abstract/cacheforserviceroot.cpp @@ -39,10 +39,6 @@ void CacheForServiceRoot::addLabelsAssignmentsToCache(const QList& ids_ } } } - - auto xx = m_cachedLabelAssignments.values(); - auto xxx = m_cachedLabelDeassignments.values(); - int a = 5; } void CacheForServiceRoot::addMessageStatesToCache(const QList& ids_of_messages, RootItem::Importance importance) { diff --git a/src/librssguard/services/abstract/label.cpp b/src/librssguard/services/abstract/label.cpp index bc60ef0fd..ead4ea3d1 100755 --- a/src/librssguard/services/abstract/label.cpp +++ b/src/librssguard/services/abstract/label.cpp @@ -104,20 +104,20 @@ QIcon Label::generateIcon(const QColor& color) { void Label::assignToMessage(const Message& msg) { QSqlDatabase database = qApp->database()->connection(metaObject()->className()); - if (getParentServiceRoot()->onBeforeLabelMessageAssignmentChanged({this}, {msg}, true)) { + if (getParentServiceRoot()->onBeforeLabelMessageAssignmentChanged({ this }, { msg }, true)) { DatabaseQueries::assignLabelToMessage(database, this, msg); - getParentServiceRoot()->onAfterLabelMessageAssignmentChanged({this}, {msg}, true); + getParentServiceRoot()->onAfterLabelMessageAssignmentChanged({ this }, { msg }, true); } } void Label::deassignFromMessage(const Message& msg) { QSqlDatabase database = qApp->database()->connection(metaObject()->className()); - if (getParentServiceRoot()->onBeforeLabelMessageAssignmentChanged({this}, {msg}, false)) { + if (getParentServiceRoot()->onBeforeLabelMessageAssignmentChanged({ this }, { msg }, false)) { DatabaseQueries::deassignLabelFromMessage(database, this, msg); - getParentServiceRoot()->onAfterLabelMessageAssignmentChanged({this}, {msg}, false); + getParentServiceRoot()->onAfterLabelMessageAssignmentChanged({ this }, { msg }, false); } } diff --git a/src/librssguard/services/abstract/rootitem.h b/src/librssguard/services/abstract/rootitem.h index 41752fae9..5e3aab119 100644 --- a/src/librssguard/services/abstract/rootitem.h +++ b/src/librssguard/services/abstract/rootitem.h @@ -226,7 +226,11 @@ inline void RootItem::clearChildren() { } inline void RootItem::setChildItems(const QList& child_items) { - m_childItems = child_items; + clearChildren(); + + for (RootItem* ch : child_items) { + appendChild(ch); + } } RootItem::Kind operator|(RootItem::Kind a, RootItem::Kind b); diff --git a/src/librssguard/services/inoreader/definitions.h b/src/librssguard/services/inoreader/definitions.h index d3e927dc1..051521c02 100644 --- a/src/librssguard/services/inoreader/definitions.h +++ b/src/librssguard/services/inoreader/definitions.h @@ -23,7 +23,7 @@ #define INOREADER_STATE_IMPORTANT "state/com.google/starred" #define INOREADER_API_FEED_CONTENTS "https://www.inoreader.com/reader/api/0/stream/contents" -#define INOREADER_API_LIST_LABELS "https://www.inoreader.com/reader/api/0/tag/list" +#define INOREADER_API_LIST_LABELS "https://www.inoreader.com/reader/api/0/tag/list?types=1" #define INOREADER_API_LIST_FEEDS "https://www.inoreader.com/reader/api/0/subscription/list" #define INOREADER_API_EDIT_TAG "https://www.inoreader.com/reader/api/0/edit-tag" diff --git a/src/librssguard/services/inoreader/inoreaderserviceroot.cpp b/src/librssguard/services/inoreader/inoreaderserviceroot.cpp index 096e59fe8..97f9a357c 100644 --- a/src/librssguard/services/inoreader/inoreaderserviceroot.cpp +++ b/src/librssguard/services/inoreader/inoreaderserviceroot.cpp @@ -7,6 +7,7 @@ #include "miscellaneous/iconfactory.h" #include "network-web/oauth2service.h" #include "services/abstract/importantnode.h" +#include "services/abstract/labelsnode.h" #include "services/abstract/recyclebin.h" #include "services/inoreader/gui/formeditinoreaderaccount.h" #include "services/inoreader/inoreaderentrypoint.h" @@ -129,7 +130,22 @@ QString InoreaderServiceRoot::additionalTooltip() const { } RootItem* InoreaderServiceRoot::obtainNewTreeForSyncIn() const { - return m_network->feedsCategories(true); + auto tree = m_network->feedsCategories(true); + + if (tree->childCount() > 1) { + auto* lblroot = new LabelsNode(tree); + auto labels = m_network->getLabels(); + + lblroot->setChildItems(labels); + tree->appendChild(lblroot); + + return tree; + } + else { + return nullptr; + } + + return tree; } void InoreaderServiceRoot::saveAllCachedData(bool async) { diff --git a/src/librssguard/services/inoreader/network/inoreadernetworkfactory.cpp b/src/librssguard/services/inoreader/network/inoreadernetworkfactory.cpp index 4718ce2d7..f7e9a6714 100644 --- a/src/librssguard/services/inoreader/network/inoreadernetworkfactory.cpp +++ b/src/librssguard/services/inoreader/network/inoreadernetworkfactory.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -105,6 +106,52 @@ RootItem* InoreaderNetworkFactory::feedsCategories(bool obtain_icons) { return decodeFeedCategoriesData(category_data, feed_data, obtain_icons); } +QList InoreaderNetworkFactory::getLabels() { + QList lbls; + Downloader downloader; + QEventLoop loop; + QString bearer = m_oauth2->bearer().toLocal8Bit(); + + if (bearer.isEmpty()) { + return lbls; + } + + downloader.appendRawHeader(QString(HTTP_HEADERS_AUTHORIZATION).toLocal8Bit(), bearer.toLocal8Bit()); + + // We need to quit event loop when the download finishes. + connect(&downloader, &Downloader::completed, &loop, &QEventLoop::quit); + downloader.downloadFile(INOREADER_API_LIST_LABELS, qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt()); + loop.exec(); + + QString lbls_data = downloader.lastOutputData(); + QJsonDocument json_lbls = QJsonDocument::fromJson(lbls_data.toUtf8()); + + for (const QJsonValue& lbl_val : json_lbls.object()["tags"].toArray()) { + QJsonObject lbl_obj = lbl_val.toObject(); + + if (lbl_obj["type"] == QL1S("tag")) { + QString name_id = lbl_obj["id"].toString(); + QString id = QRegularExpression("user\\/(\\d+)\\/").match(name_id).captured(1); + QString plain_name = QRegularExpression(".+\\/([^\\/]+)").match(name_id).captured(1); + quint32 color = 0; + + for (const QChar chr : name_id) { + color += chr.unicode(); + } + + color = QRandomGenerator(color).bounded(double(0xFFFFFF)) - 1; + + auto color_name = QSL("#%1").arg(color, 6, 16); + auto* new_lbl = new Label(plain_name, QColor(color_name)); + + new_lbl->setCustomId(name_id); + lbls.append(new_lbl); + } + } + + return lbls; +} + QList InoreaderNetworkFactory::messages(const QString& stream_id, Feed::Status& error) { Downloader downloader; QEventLoop loop; @@ -376,9 +423,10 @@ RootItem* InoreaderNetworkFactory::decodeFeedCategoriesData(const QString& categ for (const QJsonValue& obj : json) { auto label = obj.toObject(); - QString label_id = label["id"].toString(); - if (label_id.contains(QSL("/label/"))) { + if (label["type"].toString() == QL1S("folder")) { + QString label_id = label["id"].toString(); + // We have label (not "state"). auto* category = new Category(); diff --git a/src/librssguard/services/inoreader/network/inoreadernetworkfactory.h b/src/librssguard/services/inoreader/network/inoreadernetworkfactory.h index c95cbd905..30c54649a 100644 --- a/src/librssguard/services/inoreader/network/inoreadernetworkfactory.h +++ b/src/librssguard/services/inoreader/network/inoreadernetworkfactory.h @@ -38,6 +38,8 @@ class InoreaderNetworkFactory : public QObject { // Returned items do not have primary IDs assigned. RootItem* feedsCategories(bool obtain_icons); + QList getLabels(); + QList messages(const QString& stream_id, Feed::Status& error); void markMessagesRead(RootItem::ReadStatus status, const QStringList& custom_ids, bool async = true); void markMessagesStarred(RootItem::Importance importance, const QStringList& custom_ids, bool async = true); diff --git a/src/librssguard/services/tt-rss/ttrssserviceroot.cpp b/src/librssguard/services/tt-rss/ttrssserviceroot.cpp index e4ae7a009..7834bd465 100644 --- a/src/librssguard/services/tt-rss/ttrssserviceroot.cpp +++ b/src/librssguard/services/tt-rss/ttrssserviceroot.cpp @@ -168,6 +168,19 @@ void TtRssServiceRoot::saveAllCachedData(bool async) { network()->setArticleLabel(messages, label_custom_id, true); } } + + QMapIterator l(msg_cache.m_cachedLabelDeassignments); + + // Remove label from these messages. + while (l.hasNext()) { + l.next(); + auto label_custom_id = l.key(); + QStringList messages = l.value(); + + if (!messages.isEmpty()) { + network()->setArticleLabel(messages, label_custom_id, false); + } + } } QString TtRssServiceRoot::additionalTooltip() const {