display notifications when login failure etc.

This commit is contained in:
Martin Rotter 2021-08-13 11:11:57 +02:00
parent 0ff6e86c62
commit b1e45623c5
10 changed files with 128 additions and 103 deletions

View File

@ -10,7 +10,11 @@
NotificationsEditor::NotificationsEditor(QWidget* parent) : QScrollArea(parent), m_layout(new QVBoxLayout(this)) { NotificationsEditor::NotificationsEditor(QWidget* parent) : QScrollArea(parent), m_layout(new QVBoxLayout(this)) {
m_ui.setupUi(this); m_ui.setupUi(this);
setLayout(m_layout);
QWidget* wdg = new QWidget(this);
wdg->setLayout(m_layout);
setWidget(wdg);
} }
void NotificationsEditor::loadNotifications(const QList<Notification>& notifications) { void NotificationsEditor::loadNotifications(const QList<Notification>& notifications) {

View File

@ -13,6 +13,9 @@
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::NoFrame</enum> <enum>QFrame::NoFrame</enum>
</property> </property>
<property name="widgetResizable">
<bool>true</bool>
</property>
</widget> </widget>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -25,7 +25,7 @@ SingleNotificationEditor::SingleNotificationEditor(const Notification& notificat
connect(m_ui.m_txtSound, &QLineEdit::textChanged, this, &SingleNotificationEditor::notificationChanged); connect(m_ui.m_txtSound, &QLineEdit::textChanged, this, &SingleNotificationEditor::notificationChanged);
connect(m_ui.m_cbBalloon, &QCheckBox::toggled, this, &SingleNotificationEditor::notificationChanged); connect(m_ui.m_cbBalloon, &QCheckBox::toggled, this, &SingleNotificationEditor::notificationChanged);
//setFixedHeight(sizeHint().height()); setFixedHeight(sizeHint().height());
} }
Notification SingleNotificationEditor::notification() const { Notification SingleNotificationEditor::notification() const {

View File

@ -95,13 +95,11 @@ Application::Application(const QString& id, int& argc, char** argv)
if (isFirstRun()) { if (isFirstRun()) {
m_notifications->save({ m_notifications->save({
Notification(Notification::Event::GeneralEvent, Notification(Notification::Event::GeneralEvent, true),
true), Notification(Notification::Event::NewUnreadArticlesFetched, true,
Notification(Notification::Event::NewUnreadArticlesFetched,
true,
QSL("%1/rooster.wav").arg(SOUNDS_BUILTIN_DIRECTORY)), QSL("%1/rooster.wav").arg(SOUNDS_BUILTIN_DIRECTORY)),
Notification(Notification::Event::NewAppVersionAvailable, Notification(Notification::Event::NewAppVersionAvailable, true),
true) Notification(Notification::Event::LoginFailure, true)
}, settings()); }, settings());
} }
else { else {
@ -254,8 +252,7 @@ void Application::eliminateFirstRuns() {
settings()->setValue(GROUP(General), QString(General::FirstRun) + QL1C('_') + APP_VERSION, false); settings()->setValue(GROUP(General), QString(General::FirstRun) + QL1C('_') + APP_VERSION, false);
} }
NotificationFactory* Application::notifications() const NotificationFactory* Application::notifications() const {
{
return m_notifications; return m_notifications;
} }

View File

@ -43,6 +43,7 @@ QList<Notification::Event> Notification::allEvents() {
Event::NewUnreadArticlesFetched, Event::NewUnreadArticlesFetched,
Event::ArticlesFetchingStarted, Event::ArticlesFetchingStarted,
Event::LoginDataRefreshed, Event::LoginDataRefreshed,
Event::LoginFailure,
Event::NewAppVersionAvailable, Event::NewAppVersionAvailable,
}; };
} }
@ -58,6 +59,9 @@ QString Notification::nameForEvent(Notification::Event event) {
case Notification::Event::LoginDataRefreshed: case Notification::Event::LoginDataRefreshed:
return QObject::tr("Login data refreshed"); return QObject::tr("Login data refreshed");
case Notification::Event::LoginFailure:
return QObject::tr("Login failed");
case Notification::Event::NewAppVersionAvailable: case Notification::Event::NewAppVersionAvailable:
return QObject::tr("New %1 version is available").arg(APP_NAME); return QObject::tr("New %1 version is available").arg(APP_NAME);

View File

@ -28,7 +28,9 @@ class Notification {
// OAuth or similar mechanism. // OAuth or similar mechanism.
LoginDataRefreshed = 4, LoginDataRefreshed = 4,
NewAppVersionAvailable = 5 NewAppVersionAvailable = 5,
LoginFailure = 6
}; };
explicit Notification(Event event = Event::NoEvent, bool balloon = {}, const QString& sound_path = {}); explicit Notification(Event event = Event::NoEvent, bool balloon = {}, const QString& sound_path = {});

View File

@ -80,7 +80,7 @@ OAuth2Service::~OAuth2Service() {
QString OAuth2Service::bearer() { QString OAuth2Service::bearer() {
if (!isFullyLoggedIn()) { if (!isFullyLoggedIn()) {
qApp->showGuiMessage(Notification::Event::GeneralEvent, qApp->showGuiMessage(Notification::Event::LoginFailure,
tr("You have to login first"), tr("You have to login first"),
tr("Click here to login."), tr("Click here to login."),
QSystemTrayIcon::MessageIcon::Critical, QSystemTrayIcon::MessageIcon::Critical,

View File

@ -433,7 +433,7 @@ void GmailNetworkFactory::onTokensError(const QString& error, const QString& err
} }
void GmailNetworkFactory::onAuthFailed() { void GmailNetworkFactory::onAuthFailed() {
qApp->showGuiMessage(Notification::Event::GeneralEvent, qApp->showGuiMessage(Notification::Event::LoginFailure,
tr("Gmail: authorization denied"), tr("Gmail: authorization denied"),
tr("Click this to login again."), tr("Click this to login again."),
QSystemTrayIcon::MessageIcon::Critical, QSystemTrayIcon::MessageIcon::Critical,

View File

@ -5,6 +5,7 @@
#include "3rd-party/boolinq/boolinq.h" #include "3rd-party/boolinq/boolinq.h"
#include "database/databasequeries.h" #include "database/databasequeries.h"
#include "exceptions/applicationexception.h" #include "exceptions/applicationexception.h"
#include "exceptions/feedfetchexception.h"
#include "exceptions/networkexception.h" #include "exceptions/networkexception.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "network-web/networkfactory.h" #include "network-web/networkfactory.h"
@ -22,9 +23,9 @@
GreaderNetwork::GreaderNetwork(QObject* parent) GreaderNetwork::GreaderNetwork(QObject* parent)
: QObject(parent), m_root(nullptr), m_service(GreaderServiceRoot::Service::FreshRss), m_username(QString()), : QObject(parent), m_root(nullptr), m_service(GreaderServiceRoot::Service::FreshRss), m_username(QString()),
m_password(QString()), m_baseUrl(QString()), m_batchSize(GREADER_DEFAULT_BATCH_SIZE), m_downloadOnlyUnreadMessages(false), m_password(QString()), m_baseUrl(QString()), m_batchSize(GREADER_DEFAULT_BATCH_SIZE), m_downloadOnlyUnreadMessages(false),
m_prefetchedMessages({}), m_performGlobalFetching(false), m_intelligentSynchronization(true), m_prefetchedMessages({}), m_prefetchedStatus(Feed::Status::Normal), m_performGlobalFetching(false),
m_newerThanFilter(QDate::currentDate().addYears(-1)), m_intelligentSynchronization(true), m_newerThanFilter(QDate::currentDate().addYears(-1)),
m_oauth2(new OAuth2Service(INO_OAUTH_AUTH_URL, INO_OAUTH_TOKEN_URL, m_oauth(new OAuth2Service(INO_OAUTH_AUTH_URL, INO_OAUTH_TOKEN_URL,
{}, {}, INO_OAUTH_SCOPE, this)) { {}, {}, INO_OAUTH_SCOPE, this)) {
initializeOauth(); initializeOauth();
clearCredentials(); clearCredentials();
@ -129,6 +130,7 @@ QVariantHash GreaderNetwork::userInfo(const QNetworkProxy& proxy) {
void GreaderNetwork::clearPrefetchedMessages() { void GreaderNetwork::clearPrefetchedMessages() {
m_prefetchedMessages.clear(); m_prefetchedMessages.clear();
m_prefetchedStatus = Feed::Status::Normal;
} }
void GreaderNetwork::prepareFeedFetching(GreaderServiceRoot* root, void GreaderNetwork::prepareFeedFetching(GreaderServiceRoot* root,
@ -139,6 +141,9 @@ void GreaderNetwork::prepareFeedFetching(GreaderServiceRoot* root,
Q_UNUSED(tagged_messages) Q_UNUSED(tagged_messages)
m_prefetchedMessages.clear(); m_prefetchedMessages.clear();
m_prefetchedStatus = Feed::Status::Normal;
try {
double perc_of_fetching = (feeds.size() * 1.0) / root->getSubTreeFeeds().size(); double perc_of_fetching = (feeds.size() * 1.0) / root->getSubTreeFeeds().size();
@ -231,6 +236,10 @@ void GreaderNetwork::prepareFeedFetching(GreaderServiceRoot* root,
m_prefetchedMessages = itemContents(root, to_download_list, error, proxy); m_prefetchedMessages = itemContents(root, to_download_list, error, proxy);
} }
} }
catch (const FeedFetchException& fex) {
m_prefetchedStatus = fex.feedStatus();
}
}
QList<Message> GreaderNetwork::getMessagesIntelligently(ServiceRoot* root, QList<Message> GreaderNetwork::getMessagesIntelligently(ServiceRoot* root,
const QString& stream_id, const QString& stream_id,
@ -242,6 +251,11 @@ QList<Message> GreaderNetwork::getMessagesIntelligently(ServiceRoot* root,
QList<Message> msgs; QList<Message> msgs;
if (m_prefetchedStatus != Feed::Status::Normal) {
error = m_prefetchedStatus;
return msgs;
}
if (!m_performGlobalFetching) { if (!m_performGlobalFetching) {
// 1. Get unread IDs for a feed. // 1. Get unread IDs for a feed.
// 2. Get read IDs for a feed. // 2. Get read IDs for a feed.
@ -339,7 +353,7 @@ QStringList GreaderNetwork::itemIds(const QString& stream_id, bool unread_only,
QString continuation; QString continuation;
if (!ensureLogin(proxy)) { if (!ensureLogin(proxy)) {
throw ApplicationException(tr("login failed")); throw FeedFetchException(Feed::Status::AuthError, tr("login failed"));
} }
QStringList ids; QStringList ids;
@ -839,7 +853,7 @@ void GreaderNetwork::setBaseUrl(const QString& base_url) {
QPair<QByteArray, QByteArray> GreaderNetwork::authHeader() const { QPair<QByteArray, QByteArray> GreaderNetwork::authHeader() const {
if (m_service == GreaderServiceRoot::Service::Inoreader) { if (m_service == GreaderServiceRoot::Service::Inoreader) {
return { QString(HTTP_HEADERS_AUTHORIZATION).toLocal8Bit(), return { QString(HTTP_HEADERS_AUTHORIZATION).toLocal8Bit(),
m_oauth2->bearer().toLocal8Bit() }; m_oauth->bearer().toLocal8Bit() };
} }
else { else {
return { QSL(HTTP_HEADERS_AUTHORIZATION).toLocal8Bit(), return { QSL(HTTP_HEADERS_AUTHORIZATION).toLocal8Bit(),
@ -849,7 +863,7 @@ QPair<QByteArray, QByteArray> GreaderNetwork::authHeader() const {
bool GreaderNetwork::ensureLogin(const QNetworkProxy& proxy, QNetworkReply::NetworkError* output) { bool GreaderNetwork::ensureLogin(const QNetworkProxy& proxy, QNetworkReply::NetworkError* output) {
if (m_service == GreaderServiceRoot::Service::Inoreader) { if (m_service == GreaderServiceRoot::Service::Inoreader) {
return !m_oauth2->bearer().isEmpty(); return !m_oauth->bearer().isEmpty();
} }
if (m_authSid.isEmpty() && m_authAuth.isEmpty()) { if (m_authSid.isEmpty() && m_authAuth.isEmpty()) {
@ -1073,20 +1087,20 @@ void GreaderNetwork::onTokensError(const QString& error, const QString& error_de
QSystemTrayIcon::MessageIcon::Critical, QSystemTrayIcon::MessageIcon::Critical,
{}, {}, {}, {},
[this]() { [this]() {
m_oauth2->setAccessToken(QString()); m_oauth->setAccessToken(QString());
m_oauth2->setRefreshToken(QString()); m_oauth->setRefreshToken(QString());
m_oauth2->login(); m_oauth->login();
}); });
} }
void GreaderNetwork::onAuthFailed() { void GreaderNetwork::onAuthFailed() {
qApp->showGuiMessage(Notification::Event::GeneralEvent, qApp->showGuiMessage(Notification::Event::LoginFailure,
tr("Inoreader: authorization denied"), tr("Inoreader: authorization denied"),
tr("Click this to login again."), tr("Click this to login again."),
QSystemTrayIcon::MessageIcon::Critical, QSystemTrayIcon::MessageIcon::Critical,
{}, {}, {}, {},
[this]() { [this]() {
m_oauth2->login(); m_oauth->login();
}); });
} }
@ -1096,14 +1110,14 @@ void GreaderNetwork::initializeOauth() {
m_oauth2->setClientSecretSecret(TextFactory::decrypt(INOREADER_CLIENT_SECRET, OAUTH_DECRYPTION_KEY)); m_oauth2->setClientSecretSecret(TextFactory::decrypt(INOREADER_CLIENT_SECRET, OAUTH_DECRYPTION_KEY));
#endif #endif
m_oauth2->setRedirectUrl(QString(OAUTH_REDIRECT_URI) + m_oauth->setRedirectUrl(QString(OAUTH_REDIRECT_URI) +
QL1C(':') + QL1C(':') +
QString::number(INO_OAUTH_REDIRECT_URI_PORT), QString::number(INO_OAUTH_REDIRECT_URI_PORT),
false); false);
connect(m_oauth2, &OAuth2Service::tokensRetrieveError, this, &GreaderNetwork::onTokensError); connect(m_oauth, &OAuth2Service::tokensRetrieveError, this, &GreaderNetwork::onTokensError);
connect(m_oauth2, &OAuth2Service::authFailed, this, &GreaderNetwork::onAuthFailed); connect(m_oauth, &OAuth2Service::authFailed, this, &GreaderNetwork::onAuthFailed);
connect(m_oauth2, &OAuth2Service::tokensRetrieved, this, [this](QString access_token, QString refresh_token, int expires_in) { connect(m_oauth, &OAuth2Service::tokensRetrieved, this, [this](QString access_token, QString refresh_token, int expires_in) {
Q_UNUSED(expires_in) Q_UNUSED(expires_in)
Q_UNUSED(access_token) Q_UNUSED(access_token)
@ -1124,11 +1138,11 @@ void GreaderNetwork::setNewerThanFilter(const QDate& newer_than) {
} }
OAuth2Service* GreaderNetwork::oauth() const { OAuth2Service* GreaderNetwork::oauth() const {
return m_oauth2; return m_oauth;
} }
void GreaderNetwork::setOauth(OAuth2Service* oauth) { void GreaderNetwork::setOauth(OAuth2Service* oauth) {
m_oauth2 = oauth; m_oauth = oauth;
} }
void GreaderNetwork::setRoot(GreaderServiceRoot* root) { void GreaderNetwork::setRoot(GreaderServiceRoot* root) {

View File

@ -132,10 +132,11 @@ class GreaderNetwork : public QObject {
QString m_authAuth; QString m_authAuth;
QString m_authToken; QString m_authToken;
QList<Message> m_prefetchedMessages; QList<Message> m_prefetchedMessages;
Feed::Status m_prefetchedStatus;
bool m_performGlobalFetching; bool m_performGlobalFetching;
bool m_intelligentSynchronization; bool m_intelligentSynchronization;
QDate m_newerThanFilter; QDate m_newerThanFilter;
OAuth2Service* m_oauth2; OAuth2Service* m_oauth;
}; };
#endif // GREADERNETWORK_H #endif // GREADERNETWORK_H