diff --git a/resources/desktop/com.github.rssguard.appdata.xml b/resources/desktop/com.github.rssguard.appdata.xml
index 53f61d800..f8b9a18fc 100644
--- a/resources/desktop/com.github.rssguard.appdata.xml
+++ b/resources/desktop/com.github.rssguard.appdata.xml
@@ -30,7 +30,7 @@
https://martinrotter.github.io/donate/
-
+
none
diff --git a/src/librssguard/core/feeddownloader.cpp b/src/librssguard/core/feeddownloader.cpp
index e7d0cd52f..f5480c3ce 100644
--- a/src/librssguard/core/feeddownloader.cpp
+++ b/src/librssguard/core/feeddownloader.cpp
@@ -127,27 +127,27 @@ void FeedDownloader::updateOneFeed(Feed* feed) {
QSqlDatabase database = is_main_thread ?
qApp->database()->driver()->connection(metaObject()->className()) :
qApp->database()->driver()->connection(QSL("feed_upd"));
- QHash> stated_messages;
+ QHash> stated_messages;
QHash tagged_messages;
if (feed->getParentServiceRoot()->wantsBaggedIdsOfExistingMessages()) {
// This account has activated intelligent downloading of messages.
// Prepare bags.
- stated_messages.insert(feed->customId(),
- { ServiceRoot::BagOfMessages::Read,
- DatabaseQueries::bagOfMessages(database,
- ServiceRoot::BagOfMessages::Read,
- feed) });
- stated_messages.insert(feed->customId(),
- { ServiceRoot::BagOfMessages::Unread,
- DatabaseQueries::bagOfMessages(database,
- ServiceRoot::BagOfMessages::Unread,
- feed) });
- stated_messages.insert(feed->customId(),
- { ServiceRoot::BagOfMessages::Starred,
- DatabaseQueries::bagOfMessages(database,
- ServiceRoot::BagOfMessages::Starred,
- feed) });
+ QHash per_feed_states;
+
+ per_feed_states.insert(ServiceRoot::BagOfMessages::Read,
+ DatabaseQueries::bagOfMessages(database,
+ ServiceRoot::BagOfMessages::Read,
+ feed));
+ per_feed_states.insert(ServiceRoot::BagOfMessages::Unread,
+ DatabaseQueries::bagOfMessages(database,
+ ServiceRoot::BagOfMessages::Unread,
+ feed));
+ per_feed_states.insert(ServiceRoot::BagOfMessages::Starred,
+ DatabaseQueries::bagOfMessages(database,
+ ServiceRoot::BagOfMessages::Starred,
+ feed));
+ stated_messages.insert(feed->customId(), per_feed_states);
tagged_messages = DatabaseQueries::bagsOfMessages(database,
feed->getParentServiceRoot()->labelsNode()->labels());
diff --git a/src/librssguard/core/messagesmodelsqllayer.cpp b/src/librssguard/core/messagesmodelsqllayer.cpp
index dcb4c4b13..3f094b589 100644
--- a/src/librssguard/core/messagesmodelsqllayer.cpp
+++ b/src/librssguard/core/messagesmodelsqllayer.cpp
@@ -39,9 +39,10 @@ MessagesModelSqlLayer::MessagesModelSqlLayer()
<< MSG_DB_SCORE_INDEX;
}
-void MessagesModelSqlLayer::addSortState(int column, Qt::SortOrder order) {
+void MessagesModelSqlLayer::addSortState(int column, Qt::SortOrder order, bool ignore_multicolumn_sorting) {
int existing = m_sortColumns.indexOf(column);
- bool is_ctrl_pressed = (QApplication::queryKeyboardModifiers() & Qt::ControlModifier) == Qt::ControlModifier;
+ bool is_ctrl_pressed = (QApplication::queryKeyboardModifiers() &
+ Qt::KeyboardModifier::ControlModifier) == Qt::KeyboardModifier::ControlModifier;
if (existing >= 0) {
m_sortColumns.removeAt(existing);
@@ -55,14 +56,18 @@ void MessagesModelSqlLayer::addSortState(int column, Qt::SortOrder order) {
m_sortOrders.removeAt(0);
}
- if (is_ctrl_pressed) {
+ if (is_ctrl_pressed && !ignore_multicolumn_sorting) {
// User is activating the multicolumn sort mode.
m_sortColumns.append(column);
m_sortOrders.append(order);
+
+ qDebugNN << "CTRL is pressed while sorting articles - sorting with multicolumn mode.";
}
else {
m_sortColumns.prepend(column);
m_sortOrders.prepend(order);
+
+ qDebugNN << "CTRL is NOT pressed while sorting articles - sorting with standard mode.";
}
}
diff --git a/src/librssguard/core/messagesmodelsqllayer.h b/src/librssguard/core/messagesmodelsqllayer.h
index 1a8729ed4..cc2a884ec 100644
--- a/src/librssguard/core/messagesmodelsqllayer.h
+++ b/src/librssguard/core/messagesmodelsqllayer.h
@@ -13,7 +13,7 @@ class MessagesModelSqlLayer {
explicit MessagesModelSqlLayer();
// Adds this new state to queue of sort states.
- void addSortState(int column, Qt::SortOrder order);
+ void addSortState(int column, Qt::SortOrder order, bool ignore_multicolumn_sorting);
// Sets SQL WHERE clause, without "WHERE" keyword.
void setFilter(const QString& filter);
diff --git a/src/librssguard/database/databasequeries.cpp b/src/librssguard/database/databasequeries.cpp
index c547cfb24..d16605096 100755
--- a/src/librssguard/database/databasequeries.cpp
+++ b/src/librssguard/database/databasequeries.cpp
@@ -982,9 +982,10 @@ QStringList DatabaseQueries::bagOfMessages(const QSqlDatabase& db, ServiceRoot::
q.prepare(QSL("SELECT custom_id "
"FROM Messages "
- "WHERE %1 AND account_id = :account_id;").arg(query));
+ "WHERE %1 AND feed = :feed AND account_id = :account_id;").arg(query));
q.bindValue(QSL(":account_id"), feed->getParentServiceRoot()->accountId());
+ q.bindValue(QSL(":feed"), feed->customId());
q.exec();
while (q.next()) {
@@ -1277,22 +1278,20 @@ QPair DatabaseQueries::updateMessages(QSqlDatabase db,
//
// 4) FOR ALL SERVICES: Message update is forced, we want to overwrite message as some arbitrary atribute was changed,
// this particularly happens when manual message filter execution happens.
- if (/* 1 */ (!message.m_customId.isEmpty() && feed->getParentServiceRoot()->isSyncable() &&
- (message.m_created.toMSecsSinceEpoch() != date_existing_message ||
- message.m_isRead != is_read_existing_message ||
- message.m_isImportant != is_important_existing_message ||
- message.m_feedId != feed_id_existing_message ||
- message.m_title != title_existing_message ||
- message.m_contents != contents_existing_message)) ||
+ bool cond_1 = !message.m_customId.isEmpty() && feed->getParentServiceRoot()->isSyncable() &&
+ (message.m_created.toMSecsSinceEpoch() != date_existing_message ||
+ message.m_isRead != is_read_existing_message ||
+ message.m_isImportant != is_important_existing_message ||
+ message.m_feedId != feed_id_existing_message ||
+ message.m_title != title_existing_message ||
+ message.m_contents != contents_existing_message);
+ bool cond_2 = !message.m_customId.isEmpty() && !feed->getParentServiceRoot()->isSyncable() &&
+ (message.m_title != title_existing_message ||
+ message.m_contents != contents_existing_message);
+ bool cond_3 = message.m_createdFromFeed && message.m_created.toMSecsSinceEpoch() != date_existing_message &&
+ message.m_contents != contents_existing_message;
- /* 2 */ (!message.m_customId.isEmpty() && !feed->getParentServiceRoot()->isSyncable() &&
- (message.m_title != title_existing_message ||
- message.m_contents != contents_existing_message)) ||
-
- /* 3 */ (message.m_createdFromFeed && message.m_created.toMSecsSinceEpoch() != date_existing_message &&
- message.m_contents != contents_existing_message) ||
-
- /* 4 */ force_update) {
+ if (cond_1 || cond_2 || cond_3 || force_update) {
// Message exists and is changed, update it.
query_update.bindValue(QSL(":title"), unnulifyString(message.m_title));
query_update.bindValue(QSL(":is_read"), int(message.m_isRead));
diff --git a/src/librssguard/gui/messagesview.cpp b/src/librssguard/gui/messagesview.cpp
index 723bf3ef1..da3cf5005 100644
--- a/src/librssguard/gui/messagesview.cpp
+++ b/src/librssguard/gui/messagesview.cpp
@@ -52,12 +52,15 @@ void MessagesView::reloadFontSettings() {
m_sourceModel->setupFonts();
}
-void MessagesView::sort(int column, Qt::SortOrder order, bool repopulate_data, bool change_header, bool emit_changed_from_header) {
+void MessagesView::sort(int column, Qt::SortOrder order,
+ bool repopulate_data, bool change_header,
+ bool emit_changed_from_header,
+ bool ignore_multicolumn_sorting) {
if (change_header && !emit_changed_from_header) {
header()->blockSignals(true);
}
- m_sourceModel->addSortState(column, order);
+ m_sourceModel->addSortState(column, order, ignore_multicolumn_sorting);
if (repopulate_data) {
m_sourceModel->repopulate();
@@ -94,7 +97,7 @@ void MessagesView::reloadSelections() {
const Qt::SortOrder ord = header()->sortIndicatorOrder();
// Reload the model now.
- sort(col, ord, true, false, false);
+ sort(col, ord, true, false, false, true);
// Now, we must find the same previously focused message.
if (selected_message.m_id > 0) {
@@ -363,7 +366,7 @@ void MessagesView::loadItem(RootItem* item) {
const Qt::SortOrder ord = header()->sortIndicatorOrder();
scrollToTop();
- sort(col, ord, false, true, false);
+ sort(col, ord, false, true, false, true);
m_sourceModel->loadMessages(item);
// Messages are loaded, make sure that previously
@@ -679,7 +682,7 @@ void MessagesView::adjustColumns() {
void MessagesView::onSortIndicatorChanged(int column, Qt::SortOrder order) {
// Repopulate the shit.
- sort(column, order, true, false, false);
+ sort(column, order, true, false, false, false);
emit currentMessageRemoved();
}
diff --git a/src/librssguard/gui/messagesview.h b/src/librssguard/gui/messagesview.h
index 4939bffaa..cc6f9e810 100644
--- a/src/librssguard/gui/messagesview.h
+++ b/src/librssguard/gui/messagesview.h
@@ -80,7 +80,8 @@ class MessagesView : public QTreeView {
void willReselectSameMessage();
private:
- void sort(int column, Qt::SortOrder order, bool repopulate_data, bool change_header, bool emit_changed_from_header);
+ void sort(int column, Qt::SortOrder order, bool repopulate_data,
+ bool change_header, bool emit_changed_from_header, bool ignore_multicolumn_sorting);
// Creates needed connections.
void createConnections();
diff --git a/src/librssguard/services/abstract/serviceroot.h b/src/librssguard/services/abstract/serviceroot.h
index d16198913..f37401e14 100644
--- a/src/librssguard/services/abstract/serviceroot.h
+++ b/src/librssguard/services/abstract/serviceroot.h
@@ -102,7 +102,7 @@ class ServiceRoot : public RootItem {
// Throws exception subclassed from ApplicationException, preferably FeedFetchException
// if any problems arise.
virtual QList obtainNewMessages(const QList& feeds,
- const QHash>& stated_messages,
+ const QHash>& stated_messages,
const QHash& tagged_messages) = 0;
// This method should prepare messages for given "item" (download them maybe?)
diff --git a/src/librssguard/services/feedly/feedlyserviceroot.cpp b/src/librssguard/services/feedly/feedlyserviceroot.cpp
index 77086ee83..072d45815 100755
--- a/src/librssguard/services/feedly/feedlyserviceroot.cpp
+++ b/src/librssguard/services/feedly/feedlyserviceroot.cpp
@@ -73,7 +73,7 @@ void FeedlyServiceRoot::setCustomDatabaseData(const QVariantHash& data) {
}
QList FeedlyServiceRoot::obtainNewMessages(const QList& feeds,
- const QHash>& stated_messages,
+ const QHash>& stated_messages,
const QHash& tagged_messages) {
Q_UNUSED(stated_messages)
Q_UNUSED(tagged_messages)
diff --git a/src/librssguard/services/feedly/feedlyserviceroot.h b/src/librssguard/services/feedly/feedlyserviceroot.h
index d0b1a72e5..ed79024dd 100755
--- a/src/librssguard/services/feedly/feedlyserviceroot.h
+++ b/src/librssguard/services/feedly/feedlyserviceroot.h
@@ -24,7 +24,7 @@ class FeedlyServiceRoot : public ServiceRoot, public CacheForServiceRoot {
virtual QVariantHash customDatabaseData() const;
virtual void setCustomDatabaseData(const QVariantHash& data);
virtual QList obtainNewMessages(const QList& feeds,
- const QHash>& stated_messages,
+ const QHash>& stated_messages,
const QHash& tagged_messages);
FeedlyNetwork* network() const;
diff --git a/src/librssguard/services/gmail/gmailserviceroot.cpp b/src/librssguard/services/gmail/gmailserviceroot.cpp
index f8985c810..27f5586d2 100644
--- a/src/librssguard/services/gmail/gmailserviceroot.cpp
+++ b/src/librssguard/services/gmail/gmailserviceroot.cpp
@@ -75,7 +75,7 @@ void GmailServiceRoot::setCustomDatabaseData(const QVariantHash& data) {
}
QList GmailServiceRoot::obtainNewMessages(const QList& feeds,
- const QHash>& stated_messages,
+ const QHash>& stated_messages,
const QHash& tagged_messages) {
Q_UNUSED(stated_messages)
Q_UNUSED(tagged_messages)
diff --git a/src/librssguard/services/gmail/gmailserviceroot.h b/src/librssguard/services/gmail/gmailserviceroot.h
index 58b5ba9bc..71a7dd94c 100644
--- a/src/librssguard/services/gmail/gmailserviceroot.h
+++ b/src/librssguard/services/gmail/gmailserviceroot.h
@@ -32,7 +32,7 @@ class GmailServiceRoot : public ServiceRoot, public CacheForServiceRoot {
virtual QVariantHash customDatabaseData() const;
virtual void setCustomDatabaseData(const QVariantHash& data);
virtual QList obtainNewMessages(const QList& feeds,
- const QHash>& stated_messages,
+ const QHash>& stated_messages,
const QHash& tagged_messages);
protected:
diff --git a/src/librssguard/services/greader/definitions.h b/src/librssguard/services/greader/definitions.h
index ea237fb85..ce6914dbe 100755
--- a/src/librssguard/services/greader/definitions.h
+++ b/src/librssguard/services/greader/definitions.h
@@ -27,6 +27,8 @@
#define GREADER_API_SUBSCRIPTION_LIST "reader/api/0/subscription/list?output=json"
#define GREADER_API_STREAM_CONTENTS "reader/api/0/stream/contents/%1?output=json&n=%2"
#define GREADER_API_EDIT_TAG "reader/api/0/edit-tag"
+#define GREADER_API_ITEM_IDS "reader/api/0/stream/items/ids?output=json&s=%1"
+#define GREADER_API_ITEM_CONTENTS "reader/api/0/stream/items/contents?output=json&n=%1"
#define GREADER_API_TOKEN "reader/api/0/token"
#define GREADER_API_USER_INFO "reader/api/0/user-info?output=json"
diff --git a/src/librssguard/services/greader/greadernetwork.cpp b/src/librssguard/services/greader/greadernetwork.cpp
index 9a827beeb..da0f3e063 100755
--- a/src/librssguard/services/greader/greadernetwork.cpp
+++ b/src/librssguard/services/greader/greadernetwork.cpp
@@ -120,6 +120,41 @@ QVariantHash GreaderNetwork::userInfo(const QNetworkProxy& proxy) {
return QJsonDocument::fromJson(output).object().toVariantHash();
}
+QList GreaderNetwork::getMessagesIntelligently(ServiceRoot* root,
+ const QString& stream_id,
+ const QHash& stated_messages,
+ const QHash& tagged_messages,
+ Feed::Status& error,
+ const QNetworkProxy& proxy) {
+ // 1. Get unread IDs for a feed.
+ // 2. Get read IDs for a feed.
+ // 3. Download messages/contents for missing or changed IDs.
+ // 4. Download all starred messages and append those belonging to this feed.
+
+ auto remote_all_ids_list = itemIds(stream_id, false, proxy);
+ auto remote_unread_ids_list = itemIds(stream_id, true, proxy);
+ QSet remote_all_ids(remote_all_ids_list.begin(), remote_all_ids_list.end());
+
+ // 1.
+ auto local_unread_ids_list = stated_messages.value(ServiceRoot::BagOfMessages::Unread);
+ QSet remote_unread_ids(remote_unread_ids_list.begin(), remote_unread_ids_list.end());
+ QSet local_unread_ids(local_unread_ids_list.begin(),
+ local_unread_ids_list.end());
+
+ // 2.
+ auto local_read_ids_list = stated_messages.value(ServiceRoot::BagOfMessages::Read);
+ QSet remote_read_ids = remote_all_ids - remote_unread_ids;
+ QSet local_read_ids(local_read_ids_list.begin(),
+ local_read_ids_list.end());
+ auto not_downloaded = remote_all_ids - local_read_ids - local_unread_ids;
+ auto moved_unread = local_unread_ids.intersect(remote_read_ids);
+ auto moved_read = local_read_ids.intersect(remote_unread_ids);
+ auto to_download = not_downloaded + moved_read + moved_unread;
+ QList to_download_list(to_download.begin(), to_download.end());
+
+ return itemContents(root, to_download_list, error, proxy);
+}
+
QNetworkReply::NetworkError GreaderNetwork::markMessagesRead(RootItem::ReadStatus status,
const QStringList& msg_custom_ids,
const QNetworkProxy& proxy) {
@@ -132,6 +167,115 @@ QNetworkReply::NetworkError GreaderNetwork::markMessagesStarred(RootItem::Import
return editLabels(GREADER_API_FULL_STATE_IMPORTANT, importance == RootItem::Importance::Important, msg_custom_ids, proxy);
}
+QStringList GreaderNetwork::itemIds(const QString& stream_id, bool unread_only, const QNetworkProxy& proxy) {
+ QString continuation;
+
+ if (!ensureLogin(proxy)) {
+ throw ApplicationException(tr("login failed"));
+ }
+
+ QStringList ids;
+
+ do {
+ QString full_url = generateFullUrl(Operations::ItemIds).arg(m_service == GreaderServiceRoot::Service::TheOldReader
+ ? stream_id
+ : QUrl::toPercentEncoding(stream_id));
+ auto timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
+
+ if (unread_only) {
+ full_url += QSL("&xt=%1").arg(GREADER_API_FULL_STATE_READ);
+ }
+
+ if (!continuation.isEmpty()) {
+ full_url += QSL("&c=%1").arg(continuation);
+ }
+
+ QByteArray output_stream;
+ auto result_stream = NetworkFactory::performNetworkOperation(full_url,
+ timeout,
+ {},
+ output_stream,
+ QNetworkAccessManager::Operation::GetOperation,
+ { authHeader() },
+ false,
+ {},
+ {},
+ proxy);
+
+ if (result_stream.first != QNetworkReply::NetworkError::NoError) {
+ qCriticalNN << LOGSEC_GREADER
+ << "Cannot download item IDs for "
+ << QUOTE_NO_SPACE(stream_id)
+ << ", network error:"
+ << QUOTE_W_SPACE_DOT(result_stream.first);
+ throw NetworkException(result_stream.first);
+ }
+ else {
+ ids.append(decodeItemIds(output_stream, continuation));
+ }
+ }
+ while (!continuation.isEmpty());
+
+ return ids;
+}
+
+QList GreaderNetwork::itemContents(ServiceRoot* root, const QList& stream_ids,
+ Feed::Status& error, const QNetworkProxy& proxy) {
+ QString continuation;
+
+ if (!ensureLogin(proxy)) {
+ error = Feed::Status::AuthError;
+ return {};
+ }
+
+ QList msgs;
+ int target_msgs_size = 999;
+
+ do {
+ QString full_url = generateFullUrl(Operations::ItemContents).arg(QString::number(target_msgs_size));
+ auto timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
+
+ if (!continuation.isEmpty()) {
+ full_url += QSL("&c=%1").arg(continuation);
+ }
+
+ std::list inp = boolinq::from(stream_ids).select([this](const QString& id) {
+ return QSL("i=%1").arg(m_service == GreaderServiceRoot::Service::TheOldReader
+ ? id
+ : QUrl::toPercentEncoding(id));
+ }).toStdList();
+ QByteArray input = FROM_STD_LIST(QStringList, inp).join(QSL("&")).toUtf8();
+ QByteArray output_stream;
+ auto result_stream = NetworkFactory::performNetworkOperation(full_url,
+ timeout,
+ input,
+ output_stream,
+ QNetworkAccessManager::Operation::PostOperation,
+ { authHeader() },
+ false,
+ {},
+ {},
+ proxy);
+
+ if (result_stream.first != QNetworkReply::NetworkError::NoError) {
+ qCriticalNN << LOGSEC_GREADER
+ << "Cannot download messages for "
+ << stream_ids
+ << ", network error:"
+ << QUOTE_W_SPACE_DOT(result_stream.first);
+ error = Feed::Status::NetworkError;
+ return {};
+ }
+ else {
+ msgs.append(decodeStreamContents(root, output_stream, "", continuation));
+ }
+ }
+ while (!continuation.isEmpty());
+
+ error = Feed::Status::Normal;
+ return msgs;
+}
+
QList GreaderNetwork::streamContents(ServiceRoot* root, const QString& stream_id,
Feed::Status& error, const QNetworkProxy& proxy) {
QString continuation;
@@ -548,6 +692,21 @@ QString GreaderNetwork::simplifyStreamId(const QString& stream_id) const {
return QString(stream_id).replace(QRegularExpression("\\/\\d+\\/"), QSL("/-/"));
}
+QStringList GreaderNetwork::decodeItemIds(const QString& stream_json_data, QString& continuation) {
+ QStringList ids;
+ QJsonDocument json_doc = QJsonDocument::fromJson(stream_json_data.toUtf8());
+ QJsonArray json = json_doc.object()["itemRefs"].toArray();
+
+ continuation = json_doc.object()["continuation"].toString();
+ ids.reserve(json.count());
+
+ for (const QJsonValue& id : json) {
+ ids.append(id.toObject()["id"].toString());
+ }
+
+ return ids;
+}
+
QList GreaderNetwork::decodeStreamContents(ServiceRoot* root,
const QString& stream_json_data,
const QString& stream_id,
@@ -618,7 +777,9 @@ QList GreaderNetwork::decodeStreamContents(ServiceRoot* root,
message.m_contents = message_obj["summary"].toObject()["content"].toString();
message.m_rawContents = QJsonDocument(message_obj).toJson(QJsonDocument::JsonFormat::Compact);
- message.m_feedId = stream_id;
+ message.m_feedId = stream_id.isEmpty()
+ ? message_obj["origin"].toObject()["streamId"].toString()
+ : stream_id;
messages.append(message);
}
@@ -680,6 +841,12 @@ QString GreaderNetwork::generateFullUrl(GreaderNetwork::Operations operation) co
case Operations::EditTag:
return sanitizedBaseUrl() + GREADER_API_EDIT_TAG;
+ case Operations::ItemIds:
+ return sanitizedBaseUrl() + GREADER_API_ITEM_IDS;
+
+ case Operations::ItemContents:
+ return sanitizedBaseUrl() + GREADER_API_ITEM_CONTENTS;
+
default:
return sanitizedBaseUrl();
}
diff --git a/src/librssguard/services/greader/greadernetwork.h b/src/librssguard/services/greader/greadernetwork.h
index 5ba364245..0b15690ee 100755
--- a/src/librssguard/services/greader/greadernetwork.h
+++ b/src/librssguard/services/greader/greadernetwork.h
@@ -20,7 +20,9 @@ class GreaderNetwork : public QObject {
StreamContents,
EditTag,
Token,
- UserInfo
+ UserInfo,
+ ItemIds,
+ ItemContents
};
explicit GreaderNetwork(QObject* parent = nullptr);
@@ -38,7 +40,19 @@ class GreaderNetwork : public QObject {
QVariantHash userInfo(const QNetworkProxy& proxy);
+ QList getMessagesIntelligently(ServiceRoot* root,
+ const QString& stream_id,
+ const QHash& stated_messages,
+ const QHash& tagged_messages,
+ Feed::Status& error,
+ const QNetworkProxy& proxy);
+
+ QStringList itemIds(const QString& stream_id, bool unread_only, const QNetworkProxy& proxy);
+
// Stream contents for a feed/label/etc.
+ QList itemContents(ServiceRoot* root, const QList& stream_ids,
+ Feed::Status& error, const QNetworkProxy& proxy);
+
QList streamContents(ServiceRoot* root, const QString& stream_id,
Feed::Status& error, const QNetworkProxy& proxy);
@@ -78,6 +92,7 @@ class GreaderNetwork : public QObject {
bool ensureLogin(const QNetworkProxy& proxy, QNetworkReply::NetworkError* output = nullptr);
QString simplifyStreamId(const QString& stream_id) const;
+ QStringList decodeItemIds(const QString& stream_json_data, QString& continuation);
QList decodeStreamContents(ServiceRoot* root, const QString& stream_json_data, const QString& stream_id, QString& continuation);
RootItem* decodeTagsSubscriptions(const QString& categories, const QString& feeds, bool obtain_icons, const QNetworkProxy& proxy);
QString sanitizedBaseUrl() const;
diff --git a/src/librssguard/services/greader/greaderserviceroot.cpp b/src/librssguard/services/greader/greaderserviceroot.cpp
index 81297a484..9bd25455f 100755
--- a/src/librssguard/services/greader/greaderserviceroot.cpp
+++ b/src/librssguard/services/greader/greaderserviceroot.cpp
@@ -58,7 +58,7 @@ void GreaderServiceRoot::setCustomDatabaseData(const QVariantHash& data) {
}
QList GreaderServiceRoot::obtainNewMessages(const QList& feeds,
- const QHash>& stated_messages,
+ const QHash>& stated_messages,
const QHash& tagged_messages) {
Q_UNUSED(stated_messages)
Q_UNUSED(tagged_messages)
@@ -68,7 +68,17 @@ QList GreaderServiceRoot::obtainNewMessages(const QList& feeds,
for (Feed* feed : feeds) {
Feed::Status error = Feed::Status::Normal;
- messages << network()->streamContents(this, feed->customId(), error, networkProxy());
+ if (true /* intelligent downloading */ ) {
+ messages << network()->getMessagesIntelligently(this,
+ feed->customId(),
+ stated_messages.value(feed->customId()),
+ tagged_messages,
+ error,
+ networkProxy());
+ }
+ else {
+ messages << network()->streamContents(this, feed->customId(), error, networkProxy());
+ }
if (error == Feed::Status::NetworkError || error == Feed::Status::AuthError) {
throw FeedFetchException(error);
diff --git a/src/librssguard/services/greader/greaderserviceroot.h b/src/librssguard/services/greader/greaderserviceroot.h
index d9c8df5b9..2c22c414b 100755
--- a/src/librssguard/services/greader/greaderserviceroot.h
+++ b/src/librssguard/services/greader/greaderserviceroot.h
@@ -32,7 +32,7 @@ class GreaderServiceRoot : public ServiceRoot, public CacheForServiceRoot {
virtual QVariantHash customDatabaseData() const;
virtual void setCustomDatabaseData(const QVariantHash& data);
virtual QList obtainNewMessages(const QList& feeds,
- const QHash>& stated_messages,
+ const QHash>& stated_messages,
const QHash& tagged_messages);
virtual bool wantsBaggedIdsOfExistingMessages() const;
diff --git a/src/librssguard/services/inoreader/inoreaderserviceroot.cpp b/src/librssguard/services/inoreader/inoreaderserviceroot.cpp
index 741cfd4ed..5d19c2496 100644
--- a/src/librssguard/services/inoreader/inoreaderserviceroot.cpp
+++ b/src/librssguard/services/inoreader/inoreaderserviceroot.cpp
@@ -57,7 +57,7 @@ void InoreaderServiceRoot::setCustomDatabaseData(const QVariantHash& data) {
}
QList InoreaderServiceRoot::obtainNewMessages(const QList& feeds,
- const QHash>& stated_messages,
+ const QHash>& stated_messages,
const QHash& tagged_messages) {
Q_UNUSED(stated_messages)
Q_UNUSED(tagged_messages)
diff --git a/src/librssguard/services/inoreader/inoreaderserviceroot.h b/src/librssguard/services/inoreader/inoreaderserviceroot.h
index b1dfe27a9..939f7da3a 100644
--- a/src/librssguard/services/inoreader/inoreaderserviceroot.h
+++ b/src/librssguard/services/inoreader/inoreaderserviceroot.h
@@ -30,7 +30,7 @@ class InoreaderServiceRoot : public ServiceRoot, public CacheForServiceRoot {
virtual QVariantHash customDatabaseData() const;
virtual void setCustomDatabaseData(const QVariantHash& data);
virtual QList obtainNewMessages(const QList& feeds,
- const QHash>& stated_messages,
+ const QHash>& stated_messages,
const QHash& tagged_messages);
protected:
diff --git a/src/librssguard/services/owncloud/owncloudserviceroot.cpp b/src/librssguard/services/owncloud/owncloudserviceroot.cpp
index f45221792..ad4aff717 100644
--- a/src/librssguard/services/owncloud/owncloudserviceroot.cpp
+++ b/src/librssguard/services/owncloud/owncloudserviceroot.cpp
@@ -151,7 +151,7 @@ void OwnCloudServiceRoot::setCustomDatabaseData(const QVariantHash& data) {
}
QList OwnCloudServiceRoot::obtainNewMessages(const QList& feeds,
- const QHash>& stated_messages,
+ const QHash>& stated_messages,
const QHash& tagged_messages) {
Q_UNUSED(stated_messages)
Q_UNUSED(tagged_messages)
diff --git a/src/librssguard/services/owncloud/owncloudserviceroot.h b/src/librssguard/services/owncloud/owncloudserviceroot.h
index 78600e6c3..5a15fc61d 100644
--- a/src/librssguard/services/owncloud/owncloudserviceroot.h
+++ b/src/librssguard/services/owncloud/owncloudserviceroot.h
@@ -29,7 +29,7 @@ class OwnCloudServiceRoot : public ServiceRoot, public CacheForServiceRoot {
virtual QVariantHash customDatabaseData() const;
virtual void setCustomDatabaseData(const QVariantHash& data);
virtual QList obtainNewMessages(const QList& feeds,
- const QHash>& stated_messages,
+ const QHash>& stated_messages,
const QHash& tagged_messages);
OwnCloudNetworkFactory* network() const;
diff --git a/src/librssguard/services/standard/standardserviceroot.cpp b/src/librssguard/services/standard/standardserviceroot.cpp
index 60efbd018..75bf4abbb 100644
--- a/src/librssguard/services/standard/standardserviceroot.cpp
+++ b/src/librssguard/services/standard/standardserviceroot.cpp
@@ -145,7 +145,7 @@ Qt::ItemFlags StandardServiceRoot::additionalFlags() const {
}
QList StandardServiceRoot::obtainNewMessages(const QList& feeds,
- const QHash>& stated_messages,
+ const QHash>& stated_messages,
const QHash& tagged_messages) {
Q_UNUSED(stated_messages)
Q_UNUSED(tagged_messages)
diff --git a/src/librssguard/services/standard/standardserviceroot.h b/src/librssguard/services/standard/standardserviceroot.h
index 89553f983..b1912fdc4 100644
--- a/src/librssguard/services/standard/standardserviceroot.h
+++ b/src/librssguard/services/standard/standardserviceroot.h
@@ -33,7 +33,7 @@ class StandardServiceRoot : public ServiceRoot {
virtual bool supportsCategoryAdding() const;
virtual Qt::ItemFlags additionalFlags() const;
virtual QList obtainNewMessages(const QList& feeds,
- const QHash>& stated_messages,
+ const QHash>& stated_messages,
const QHash& tagged_messages);
QList serviceMenu();
diff --git a/src/librssguard/services/tt-rss/ttrssserviceroot.cpp b/src/librssguard/services/tt-rss/ttrssserviceroot.cpp
index a1b6d7ca5..baa5cb6e7 100644
--- a/src/librssguard/services/tt-rss/ttrssserviceroot.cpp
+++ b/src/librssguard/services/tt-rss/ttrssserviceroot.cpp
@@ -215,7 +215,7 @@ void TtRssServiceRoot::setCustomDatabaseData(const QVariantHash& data) {
}
QList TtRssServiceRoot::obtainNewMessages(const QList& feeds,
- const QHash>& stated_messages,
+ const QHash>& stated_messages,
const QHash& tagged_messages) {
Q_UNUSED(stated_messages)
Q_UNUSED(tagged_messages)
diff --git a/src/librssguard/services/tt-rss/ttrssserviceroot.h b/src/librssguard/services/tt-rss/ttrssserviceroot.h
index 042be9099..195e82f9c 100644
--- a/src/librssguard/services/tt-rss/ttrssserviceroot.h
+++ b/src/librssguard/services/tt-rss/ttrssserviceroot.h
@@ -34,7 +34,7 @@ class TtRssServiceRoot : public ServiceRoot, public CacheForServiceRoot {
virtual QVariantHash customDatabaseData() const;
virtual void setCustomDatabaseData(const QVariantHash& data);
virtual QList obtainNewMessages(const QList& feeds,
- const QHash>& stated_messages,
+ const QHash>& stated_messages,
const QHash& tagged_messages);
// Access to network.