move screnshots, work on feedly

This commit is contained in:
Martin Rotter 2021-02-16 13:17:21 +01:00
parent 8aa9c19cdf
commit 3d6a289120
18 changed files with 169 additions and 57 deletions

View File

@ -17,11 +17,11 @@
<screenshots>
<screenshot type="default">
<caption>Linux version</caption>
<image>https://github.com/martinrotter/rssguard/blob/master/resources/screenshots/screenshot-linux.png?raw=true</image>
<image>https://github.com/martinrotter/rssguard/blob/master/resources/docs/images/screenshot-linux.png?raw=true</image>
</screenshot>
<screenshot>
<caption>Windows version</caption>
<image>https://github.com/martinrotter/rssguard/blob/master/resources/screenshots/screenshot-windows.png?raw=true</image>
<image>https://github.com/martinrotter/rssguard/blob/master/resources/docs/images/screenshot-windows.png?raw=true</image>
</screenshot>
</screenshots>
<url type="homepage">https://github.com/martinrotter/rssguard</url>
@ -30,7 +30,7 @@
<url type="donation">https://martinrotter.github.io/donate/</url>
<content_rating type="oars-1.1" />
<releases>
<release version="3.8.4" date="2021-02-15"/>
<release version="3.8.4" date="2021-02-16"/>
</releases>
<content_rating type="oars-1.0">
<content_attribute id="violence-cartoon">none</content_attribute>

View File

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 162 KiB

View File

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

@ -1 +1 @@
Subproject commit 9c10723bfbaf6cb85107d6ee16e0324e9e487749
Subproject commit 47f4125753452eff8800dbd6600c5a05540b15d9

View File

@ -91,6 +91,7 @@ CREATE TABLE IF NOT EXISTS FeedlyAccounts (
developer_access_token TEXT,
refresh_token TEXT,
msg_limit INTEGER NOT NULL DEFAULT -1 CHECK (msg_limit >= -1),
update_only_unread INTEGER(1) NOT NULL DEFAULT 0 CHECK (update_only_unread >= 0 AND update_only_unread <= 1),
FOREIGN KEY (id) REFERENCES Accounts (id)
);

View File

@ -85,6 +85,7 @@ CREATE TABLE IF NOT EXISTS FeedlyAccounts (
developer_access_token TEXT,
refresh_token TEXT,
msg_limit INTEGER NOT NULL DEFAULT -1 CHECK (msg_limit >= -1),
update_only_unread INTEGER(1) NOT NULL DEFAULT 0 CHECK (update_only_unread >= 0 AND update_only_unread <= 1),
FOREIGN KEY (id) REFERENCES Accounts (id)
);

View File

@ -4,6 +4,7 @@ CREATE TABLE IF NOT EXISTS FeedlyAccounts (
developer_access_token TEXT,
refresh_token TEXT,
msg_limit INTEGER NOT NULL DEFAULT -1 CHECK (msg_limit >= -1),
update_only_unread INTEGER(1) NOT NULL DEFAULT 0 CHECK (update_only_unread >= 0 AND update_only_unread <= 1),
FOREIGN KEY (id) REFERENCES Accounts (id)
);

View File

@ -4,6 +4,7 @@ CREATE TABLE IF NOT EXISTS FeedlyAccounts (
developer_access_token TEXT,
refresh_token TEXT,
msg_limit INTEGER NOT NULL DEFAULT -1 CHECK (msg_limit >= -1),
update_only_unread INTEGER(1) NOT NULL DEFAULT 0 CHECK (update_only_unread >= 0 AND update_only_unread <= 1),
FOREIGN KEY (id) REFERENCES Accounts (id)
);

View File

@ -1846,16 +1846,18 @@ bool DatabaseQueries::overwriteOwnCloudAccount(const QSqlDatabase& db, const QSt
bool DatabaseQueries::createFeedlyAccount(const QSqlDatabase& db, const QString& username,
const QString& developer_access_token, const QString& refresh_token,
int batch_size, int account_id) {
int batch_size, bool download_only_unread_messages,
int account_id) {
QSqlQuery q(db);
q.prepare("INSERT INTO FeedlyAccounts (id, username, developer_access_token, refresh_token, msg_limit) "
"VALUES (:id, :username, :developer_access_token, :refresh_token, :msg_limit);");
q.prepare("INSERT INTO FeedlyAccounts (id, username, developer_access_token, refresh_token, msg_limit, update_only_unread) "
"VALUES (:id, :username, :developer_access_token, :refresh_token, :msg_limit, :update_only_unread);");
q.bindValue(QSL(":id"), account_id);
q.bindValue(QSL(":username"), username);
q.bindValue(QSL(":developer_access_token"), developer_access_token);
q.bindValue(QSL(":refresh_token"), refresh_token);
q.bindValue(QSL(":msg_limit"), batch_size <= 0 ? FEEDLY_UNLIMITED_BATCH_SIZE : batch_size);
q.bindValue(QSL(":update_only_unread"), download_only_unread_messages ? 1 : 0);
if (q.exec()) {
return true;
@ -1870,18 +1872,21 @@ bool DatabaseQueries::createFeedlyAccount(const QSqlDatabase& db, const QString&
bool DatabaseQueries::overwriteFeedlyAccount(const QSqlDatabase& db, const QString& username,
const QString& developer_access_token, const QString& refresh_token,
int batch_size, int account_id) {
int batch_size, bool download_only_unread_messages,
int account_id) {
QSqlQuery query(db);
query.prepare("UPDATE FeedlyAccounts "
"SET username = :username, developer_access_token = :developer_access_token, "
"refresh_token = :refresh_token, msg_limit = :msg_limit "
"refresh_token = :refresh_token, msg_limit = :msg_limit, "
"update_only_unread = :update_only_unread "
"WHERE id = :id;");
query.bindValue(QSL(":id"), account_id);
query.bindValue(QSL(":username"), username);
query.bindValue(QSL(":developer_access_token"), developer_access_token);
query.bindValue(QSL(":refresh_token"), refresh_token);
query.bindValue(QSL(":msg_limit"), batch_size <= 0 ? FEEDLY_UNLIMITED_BATCH_SIZE : batch_size);
query.bindValue(QSL(":update_only_unread"), download_only_unread_messages ? 1 : 0);
if (query.exec()) {
return true;
@ -2628,6 +2633,7 @@ QList<ServiceRoot*> DatabaseQueries::getFeedlyAccounts(const QSqlDatabase& db, b
#endif
root->network()->setBatchSize(query.value(4).toInt());
root->network()->setDownloadOnlyUnreadMessages(query.value(5).toBool());
root->updateTitle();
fillBaseAccountData(db, root);

View File

@ -159,12 +159,14 @@ class DatabaseQueries {
const QString& developer_access_token,
const QString& refresh_token,
int batch_size,
bool download_only_unread_messages,
int account_id);
static bool overwriteFeedlyAccount(const QSqlDatabase& db,
const QString& username,
const QString& developer_access_token,
const QString& refresh_token,
int batch_size,
bool download_only_unread_messages,
int account_id);
// Greader account.

View File

@ -2,7 +2,8 @@
#define FEEDLY_DEFINITIONS_H
#define FEEDLY_UNLIMITED_BATCH_SIZE -1
#define FEEDLY_MAX_BATCH_SIZE 999
#define FEEDLY_DEFAULT_BATCH_SIZE 20
#define FEEDLY_MAX_BATCH_SIZE 500
#define FEEDLY_GENERATE_DAT "https://feedly.com/v3/auth/dev"
@ -20,5 +21,6 @@
#define FEEDLY_API_URL_PROFILE "profile"
#define FEEDLY_API_URL_COLLETIONS "collections"
#define FEEDLY_API_URL_TAGS "tags"
#define FEEDLY_API_URL_STREAM_CONTENTS "streams/contents?streamId=%1"
#endif // FEEDLY_DEFINITIONS_H

View File

@ -16,14 +16,8 @@ FeedlyServiceRoot* FeedlyFeed::serviceRoot() const {
}
QList<Message> FeedlyFeed::obtainNewMessages(bool* error_during_obtaining) {
return {};
/*
Feed::Status error = Feed::Status::Normal;
QList<Message> messages = serviceRoot()->network()->streamContents(getParentServiceRoot(),
customId(),
error,
getParentServiceRoot()->networkProxy());
QList<Message> messages = serviceRoot()->network()->streamContents(customId());
setStatus(error);
@ -31,5 +25,5 @@ QList<Message> FeedlyFeed::obtainNewMessages(bool* error_during_obtaining) {
*error_during_obtaining = true;
}
return messages;*/
return messages;
}

View File

@ -33,7 +33,7 @@ FeedlyNetwork::FeedlyNetwork(QObject* parent)
FEEDLY_API_SCOPE, this)),
#endif
m_username(QString()),
m_developerAccessToken(QString()), m_batchSize(FEEDLY_UNLIMITED_BATCH_SIZE) {
m_developerAccessToken(QString()), m_batchSize(FEEDLY_DEFAULT_BATCH_SIZE), m_downloadOnlyUnreadMessages(false) {
#if defined (FEEDLY_OFFICIAL_SUPPORT)
m_oauth->setRedirectUrl(QString(OAUTH_REDIRECT_URI) + QL1C(':') + QString::number(FEEDLY_API_REDIRECT_URI_PORT));
@ -44,6 +44,57 @@ FeedlyNetwork::FeedlyNetwork(QObject* parent)
#endif
}
QList<Message> FeedlyNetwork::streamContents(const QString& stream_id) {
QString bear = bearer();
if (bear.isEmpty()) {
qCriticalNN << LOGSEC_FEEDLY << "Cannot obtain personal collections, because bearer is empty.";
throw NetworkException(QNetworkReply::NetworkError::AuthenticationRequiredError);
}
int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
QByteArray output;
QString continuation;
QList<Message> messages;
// We download in batches.
do {
QString target_url = fullUrl(Service::StreamContents).arg(QString(QUrl::toPercentEncoding(stream_id)));
if (m_downloadOnlyUnreadMessages) {
target_url += QSL("&unreadOnly=true");
}
if (!continuation.isEmpty()) {
target_url += QSL("&continuation=%1").arg(continuation);
}
else if (m_batchSize > 0) {
target_url += QSL("&count=%2").arg(QString::number(m_batchSize));
}
auto result = NetworkFactory::performNetworkOperation(target_url,
timeout,
{},
output,
QNetworkAccessManager::Operation::GetOperation,
{ bearerHeader(bear) },
false,
{},
{},
m_service->networkProxy());
messages += decodeStreamContents(output);
}
while (!continuation.isEmpty());
return messages;
}
QList<Message> FeedlyNetwork::decodeStreamContents(const QByteArray& stream_contents) const {
return {};
}
RootItem* FeedlyNetwork::collections(bool obtain_icons) {
QString bear = bearer();
@ -54,11 +105,11 @@ RootItem* FeedlyNetwork::collections(bool obtain_icons) {
QString target_url = fullUrl(Service::Collections);
int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
QByteArray output_msgs;
QByteArray output;
auto result = NetworkFactory::performNetworkOperation(target_url,
timeout,
{},
output_msgs,
output,
QNetworkAccessManager::Operation::GetOperation,
{ bearerHeader(bear) },
false,
@ -70,7 +121,7 @@ RootItem* FeedlyNetwork::collections(bool obtain_icons) {
throw NetworkException(result.first);
}
return decodeCollections(output_msgs, obtain_icons, m_service->networkProxy(), timeout);
return decodeCollections(output, obtain_icons, m_service->networkProxy(), timeout);
}
RootItem* FeedlyNetwork::decodeCollections(const QByteArray& json, bool obtain_icons,
@ -190,7 +241,20 @@ QList<RootItem*> FeedlyNetwork::tags() {
throw NetworkException(result.first);
}
return {};
QJsonDocument json = QJsonDocument::fromJson(output);
QList<RootItem*> lbls;
for (const QJsonValue& tag : json.array()) {
const QJsonObject& tag_obj = tag.toObject();
QString name_id = tag_obj["id"].toString();
QString plain_name = tag_obj["label"].toString();
auto* new_lbl = new Label(plain_name, TextFactory::generateColorFromText(name_id));
new_lbl->setCustomId(name_id);
lbls.append(new_lbl);
}
return lbls;
}
QString FeedlyNetwork::username() const {
@ -278,6 +342,9 @@ QString FeedlyNetwork::fullUrl(FeedlyNetwork::Service service) const {
case Service::Tags:
return QSL(FEEDLY_API_URL_BASE) + FEEDLY_API_URL_TAGS;
case Service::StreamContents:
return QSL(FEEDLY_API_URL_BASE) + FEEDLY_API_URL_STREAM_CONTENTS;
default:
return FEEDLY_API_URL_BASE;
}
@ -297,6 +364,14 @@ QPair<QByteArray, QByteArray> FeedlyNetwork::bearerHeader(const QString& bearer)
return { QString(HTTP_HEADERS_AUTHORIZATION).toLocal8Bit(), bearer.toLocal8Bit() };
}
bool FeedlyNetwork::downloadOnlyUnreadMessages() const {
return m_downloadOnlyUnreadMessages;
}
void FeedlyNetwork::setDownloadOnlyUnreadMessages(bool download_only_unread_messages) {
m_downloadOnlyUnreadMessages = download_only_unread_messages;
}
void FeedlyNetwork::setService(FeedlyServiceRoot* service) {
m_service = service;
}

View File

@ -21,6 +21,7 @@ class FeedlyNetwork : public QObject {
explicit FeedlyNetwork(QObject* parent = nullptr);
// API operations.
QList<Message> streamContents(const QString& stream_id);
QVariantHash profile(const QNetworkProxy& network_proxy);
QList<RootItem*> tags();
RootItem* collections(bool obtain_icons);
@ -32,6 +33,9 @@ class FeedlyNetwork : public QObject {
QString developerAccessToken() const;
void setDeveloperAccessToken(const QString& dev_acc_token);
bool downloadOnlyUnreadMessages() const;
void setDownloadOnlyUnreadMessages(bool download_only_unread_messages);
int batchSize() const;
void setBatchSize(int batch_size);
@ -51,11 +55,13 @@ class FeedlyNetwork : public QObject {
enum class Service {
Profile,
Collections,
Tags
Tags,
StreamContents
};
QString fullUrl(Service service) const;
QString bearer() const;
QList<Message> decodeStreamContents(const QByteArray& stream_contents) const;
RootItem* decodeCollections(const QByteArray& json, bool obtain_icons, const QNetworkProxy& proxy, int timeout = 0) const;
QPair<QByteArray, QByteArray> bearerHeader(const QString& bearer) const;
@ -69,6 +75,7 @@ class FeedlyNetwork : public QObject {
QString m_username;
QString m_developerAccessToken;
int m_batchSize;
bool m_downloadOnlyUnreadMessages;
};
#endif // FEEDLYNETWORK_H

View File

@ -3,6 +3,8 @@
#include "services/feedly/feedlyserviceroot.h"
#include "definitions/definitions.h"
#include "exceptions/applicationexception.h"
#include "exceptions/networkexception.h"
#include "miscellaneous/application.h"
#include "miscellaneous/databasequeries.h"
#include "miscellaneous/iconfactory.h"
@ -91,6 +93,7 @@ void FeedlyServiceRoot::saveAccountDataToDatabase(bool creating_new) {
{},
#endif
m_network->batchSize(),
m_network->downloadOnlyUnreadMessages(),
accountId())) {
updateTitle();
itemChanged(QList<RootItem*>() << this);
@ -106,6 +109,7 @@ void FeedlyServiceRoot::saveAccountDataToDatabase(bool creating_new) {
{},
#endif
m_network->batchSize(),
m_network->downloadOnlyUnreadMessages(),
accountId())) {
updateTitle();
}
@ -113,6 +117,7 @@ void FeedlyServiceRoot::saveAccountDataToDatabase(bool creating_new) {
}
RootItem* FeedlyServiceRoot::obtainNewTreeForSyncIn() const {
try {
auto tree = m_network->collections(true);
auto* lblroot = new LabelsNode(tree);
auto labels = m_network->tags();
@ -122,6 +127,13 @@ RootItem* FeedlyServiceRoot::obtainNewTreeForSyncIn() const {
return tree;
}
catch (const ApplicationException& ex) {
qCriticalNN << LOGSEC_FEEDLY
<< "Failed to obtain new sync-in tree:"
<< QUOTE_W_SPACE_DOT(ex.message());
return nullptr;
}
}
void FeedlyServiceRoot::loadFromDatabase() {
QSqlDatabase database = qApp->database()->connection(metaObject()->className());

View File

@ -65,11 +65,12 @@ FeedlyAccountDetails::FeedlyAccountDetails(QWidget* parent) : QWidget(parent) {
m_ui.m_spinLimitMessages->setMinimum(FEEDLY_UNLIMITED_BATCH_SIZE);
m_ui.m_spinLimitMessages->setMaximum(FEEDLY_MAX_BATCH_SIZE);
m_ui.m_spinLimitMessages->setValue(FEEDLY_UNLIMITED_BATCH_SIZE);
m_ui.m_spinLimitMessages->setValue(FEEDLY_DEFAULT_BATCH_SIZE);
setTabOrder(m_ui.m_txtUsername->lineEdit(), m_ui.m_btnGetToken);
setTabOrder(m_ui.m_btnGetToken, m_ui.m_txtDeveloperAccessToken->lineEdit());
setTabOrder(m_ui.m_txtDeveloperAccessToken->lineEdit(), m_ui.m_spinLimitMessages);
setTabOrder(m_ui.m_txtDeveloperAccessToken->lineEdit(), m_ui.m_checkDownloadOnlyUnreadMessages);
setTabOrder(m_ui.m_checkDownloadOnlyUnreadMessages, m_ui.m_spinLimitMessages);
setTabOrder(m_ui.m_spinLimitMessages, m_ui.m_btnTestSetup);
onDeveloperAccessTokenChanged();
@ -116,9 +117,9 @@ void FeedlyAccountDetails::onAuthGranted() {
void FeedlyAccountDetails::performTest(const QNetworkProxy& custom_proxy) {
#if defined (FEEDLY_OFFICIAL_SUPPORT)
if (m_ui.m_txtDeveloperAccessToken->lineEdit()->text().simplified().isEmpty()) {
m_oauth->logout(false);
if (m_ui.m_txtDeveloperAccessToken->lineEdit()->text().simplified().isEmpty()) {
if (m_oauth->login()) {
m_ui.m_lblTestResult->setStatus(WidgetWithStatus::StatusType::Ok,
tr("You are already logged in."),

View File

@ -52,8 +52,18 @@
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<item row="4" column="0" colspan="2">
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Only download newest X messages per feed</string>
</property>
<property name="buddy">
<cstring>m_spinLimitMessages</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="m_spinLimitMessages">
<property name="maximumSize">
@ -67,19 +77,9 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Only download newest X messages per feed</string>
</property>
<property name="buddy">
<cstring>m_spinLimitMessages</cstring>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="0" colspan="2">
<item row="6" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -92,7 +92,7 @@
</property>
</spacer>
</item>
<item row="4" column="0" colspan="2">
<item row="5" column="0" colspan="2">
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QPushButton" name="m_btnTestSetup">
@ -110,6 +110,13 @@
</item>
</layout>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="m_checkDownloadOnlyUnreadMessages">
<property name="text">
<string>Download only unread messages</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>

View File

@ -44,6 +44,7 @@ void FormEditFeedlyAccount::apply() {
#endif
account<FeedlyServiceRoot>()->network()->setUsername(m_details->m_ui.m_txtUsername->lineEdit()->text());
account<FeedlyServiceRoot>()->network()->setDownloadOnlyUnreadMessages(m_details->m_ui.m_checkDownloadOnlyUnreadMessages->isChecked());
account<FeedlyServiceRoot>()->network()->setBatchSize(m_details->m_ui.m_spinLimitMessages->value());
account<FeedlyServiceRoot>()->network()->setDeveloperAccessToken(m_details->m_ui.m_txtDeveloperAccessToken->lineEdit()->text());
@ -72,6 +73,7 @@ void FormEditFeedlyAccount::setEditableAccount(ServiceRoot* editable_account) {
m_details->m_ui.m_txtUsername->lineEdit()->setText(account<FeedlyServiceRoot>()->network()->username());
m_details->m_ui.m_txtDeveloperAccessToken->lineEdit()->setText(account<FeedlyServiceRoot>()->network()->developerAccessToken());
m_details->m_ui.m_checkDownloadOnlyUnreadMessages->setChecked(account<FeedlyServiceRoot>()->network()->downloadOnlyUnreadMessages());
m_details->m_ui.m_spinLimitMessages->setValue(account<FeedlyServiceRoot>()->network()->batchSize());
}