greader supports feed deleting

This commit is contained in:
Martin Rotter 2023-11-13 12:10:58 +01:00
parent 80392d4c05
commit caecf5355a
9 changed files with 115 additions and 12 deletions

View File

@ -30,7 +30,7 @@ else {
$is_qt_6 = $qt_version.StartsWith("6")
$maria_version = "11.1.2"
$maria_link = "https://archive.mariadb.org/mariadb-$maria_version/winx64-packages/mariadb-$maria_version-winx64.zip"
$maria_link = "https://mirror.netcologne.de/mariadb/mariadb-$maria_version/winx64-packages/mariadb-$maria_version-winx64.zip"
$maria_output = "maria.zip"
$cmake_version = "3.27.7"

View File

@ -352,10 +352,16 @@ set(SOURCES
services/greader/greadernetwork.h
services/greader/greaderserviceroot.cpp
services/greader/greaderserviceroot.h
services/greader/greaderfeed.cpp
services/greader/greaderfeed.h
services/greader/gui/formeditgreaderaccount.cpp
services/greader/gui/formeditgreaderaccount.h
services/greader/gui/greaderaccountdetails.cpp
services/greader/gui/greaderaccountdetails.h
services/greader/gui/formgreaderfeeddetails.cpp
services/greader/gui/formgreaderfeeddetails.h
services/greader/gui/greaderfeeddetails.cpp
services/greader/gui/greaderfeeddetails.h
services/owncloud/definitions.h
services/owncloud/gui/formeditowncloudaccount.cpp
services/owncloud/gui/formeditowncloudaccount.h
@ -487,6 +493,7 @@ set(UI_FILES
services/gmail/gui/formaddeditemail.ui
services/gmail/gui/gmailaccountdetails.ui
services/greader/gui/greaderaccountdetails.ui
services/greader/gui/greaderfeeddetails.ui
services/owncloud/gui/owncloudaccountdetails.ui
services/reddit/gui/redditaccountdetails.ui
services/standard/gui/formdiscoverfeeds.ui

View File

@ -29,11 +29,17 @@
#define GREADER_API_EDIT_TAG "reader/api/0/edit-tag"
#define GREADER_API_SUBSCRIPTION_EXPORT "reader/api/0/subscription/export"
#define GREADER_API_SUBSCRIPTION_IMPORT "reader/api/0/subscription/import"
#define GREADER_API_SUBSCRIPTION_EDIT "reader/api/0/subscription/edit?ac=%1&s=%2"
#define GREADER_API_ITEM_IDS "reader/api/0/stream/items/ids?output=json&n=%2&s=%1"
#define GREADER_API_ITEM_CONTENTS "reader/api/0/stream/items/contents?output=json&n=200000"
#define GREADER_API_TOKEN "reader/api/0/token"
#define GREADER_API_USER_INFO "reader/api/0/user-info?output=json"
// Edit subscription ops.
#define GREADER_API_EDIT_SUBSCRIPTION_ADD "subscribe"
#define GREADER_API_EDIT_SUBSCRIPTION_MODIFY "edit"
#define GREADER_API_EDIT_SUBSCRIPTION_DELETE "unsubscribe"
// Misc.
#define GREADER_API_ITEM_IDS_MAX 200000
#define GREADER_API_EDIT_TAG_BATCH 200

View File

@ -16,6 +16,7 @@
#include "services/abstract/label.h"
#include "services/abstract/labelsnode.h"
#include "services/greader/definitions.h"
#include "services/greader/greaderfeed.h"
#include <QJsonArray>
#include <QJsonDocument>
@ -341,6 +342,57 @@ QNetworkReply::NetworkError GreaderNetwork::markMessagesStarred(RootItem::Import
proxy);
}
void GreaderNetwork::subscriptionEdit(const QString& op,
const QString& stream_id,
const QString& new_title,
const QString& set_label,
const QString& unset_label,
const QNetworkProxy& proxy) {
if (!ensureLogin(proxy)) {
throw ApplicationException(tr("login failed"));
}
QString full_url = generateFullUrl(Operations::SubscriptionEdit).arg(op, stream_id);
if (op == QSL(GREADER_API_EDIT_SUBSCRIPTION_ADD)) {
full_url += QSL("&t=%1").arg(new_title);
if (!set_label.isEmpty()) {
full_url += QSL("&a=%1").arg(set_label);
}
}
if (op == QSL(GREADER_API_EDIT_SUBSCRIPTION_MODIFY)) {
full_url += QSL("&t=%1").arg(new_title);
if (!set_label.isEmpty()) {
full_url += QSL("&a=%1").arg(set_label);
}
else if (!unset_label.isEmpty()) {
full_url += QSL("&r=%1").arg(unset_label);
}
}
auto timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
QByteArray output;
auto result = NetworkFactory::performNetworkOperation(full_url,
timeout,
{},
output,
QNetworkAccessManager::Operation::PostOperation,
{authHeader()},
false,
{},
{},
proxy);
if (result.m_networkError != QNetworkReply::NetworkError::NoError) {
qCriticalNN << LOGSEC_GREADER << "Cannot edit subscription:" << QUOTE_W_SPACE_DOT(result.m_networkError);
throw NetworkException(result.m_networkError, output);
}
}
void GreaderNetwork::subscriptionImport(const QByteArray& opml_data, const QNetworkProxy& proxy) {
if (!ensureLogin(proxy)) {
throw ApplicationException(tr("login failed"));
@ -749,7 +801,7 @@ RootItem* GreaderNetwork::decodeTagsSubscriptions(const QString& categories,
}
// We have label (not "state").
auto* feed = new Feed();
auto* feed = new GreaderFeed();
feed->setDescription(url);
feed->setSource(url);
@ -1127,6 +1179,9 @@ QString GreaderNetwork::generateFullUrl(GreaderNetwork::Operations operation) co
case Operations::SubscriptionImport:
return sanitizedBaseUrl() + QSL(GREADER_API_SUBSCRIPTION_IMPORT);
case Operations::SubscriptionEdit:
return sanitizedBaseUrl() + QSL(GREADER_API_SUBSCRIPTION_EDIT);
case Operations::Token:
return sanitizedBaseUrl() + QSL(GREADER_API_TOKEN);

View File

@ -26,7 +26,8 @@ class GreaderNetwork : public QObject {
ItemIds,
ItemContents,
SubscriptionExport,
SubscriptionImport
SubscriptionImport,
SubscriptionEdit
};
explicit GreaderNetwork(QObject* parent = nullptr);
@ -84,6 +85,12 @@ class GreaderNetwork : public QObject {
void setOauth(OAuth2Service* oauth);
// API methods.
void subscriptionEdit(const QString& op,
const QString& stream_id,
const QString& new_title,
const QString& set_label,
const QString& unset_label,
const QNetworkProxy& proxy);
void subscriptionImport(const QByteArray& opml_data, const QNetworkProxy& proxy);
QByteArray subscriptionExport(const QNetworkProxy& proxy);
QNetworkReply::NetworkError editLabels(const QString& state,

View File

@ -7,12 +7,15 @@
#include "gui/messagebox.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/mutex.h"
#include "miscellaneous/textfactory.h"
#include "network-web/oauth2service.h"
#include "services/greader/definitions.h"
#include "services/greader/greaderentrypoint.h"
#include "services/greader/greaderfeed.h"
#include "services/greader/greadernetwork.h"
#include "services/greader/gui/formeditgreaderaccount.h"
#include "services/greader/gui/formgreaderfeeddetails.h"
#include <QFileDialog>
@ -211,7 +214,7 @@ bool GreaderServiceRoot::wantsBaggedIdsOfExistingMessages() const {
void GreaderServiceRoot::start(bool freshly_activated) {
if (!freshly_activated) {
DatabaseQueries::loadRootFromDatabase<Category, Feed>(this);
DatabaseQueries::loadRootFromDatabase<Category, GreaderFeed>(this);
loadCacheFromFile();
}
@ -331,6 +334,32 @@ ServiceRoot::LabelOperation GreaderServiceRoot::supportedLabelOperations() const
return ServiceRoot::LabelOperation::Synchronised;
}
bool GreaderServiceRoot::supportsFeedAdding() const {
return true;
}
void GreaderServiceRoot::addNewFeed(RootItem* selected_item, const QString& url) {
if (!qApp->feedUpdateLock()->tryLock()) {
// Lock was not obtained because
// it is used probably by feed updater or application
// is quitting.
qApp->showGuiMessage(Notification::Event::GeneralEvent,
{tr("Cannot add item"),
tr("Cannot add feed because another critical operation is ongoing."),
QSystemTrayIcon::MessageIcon::Warning});
return;
}
QScopedPointer<FormGreaderFeedDetails> form_pointer(new FormGreaderFeedDetails(this,
selected_item,
url,
qApp->mainFormWidget()));
form_pointer->addEditFeed<GreaderFeed>();
qApp->feedUpdateLock()->unlock();
}
void GreaderServiceRoot::updateTitleIcon() {
setTitle(QSL("%1 (%2)").arg(TextFactory::extractUsernameFromEmail(m_network->username()),
GreaderServiceRoot::serviceToString(m_network->service())));

View File

@ -35,6 +35,8 @@ class GreaderServiceRoot : public ServiceRoot, public CacheForServiceRoot {
virtual QList<QAction*> serviceMenu();
virtual void saveAllCachedData(bool ignore_errors);
virtual LabelOperation supportedLabelOperations() const;
virtual bool supportsFeedAdding() const;
virtual void addNewFeed(RootItem* selected_item, const QString& url = QString());
virtual QVariantHash customDatabaseData() const;
virtual void setCustomDatabaseData(const QVariantHash& data);
virtual void aboutToBeginFeedFetching(const QList<Feed*>& feeds,

View File

@ -29,7 +29,7 @@ void FormTtRssFeedDetails::apply() {
else {
RootItem* parent = m_feedDetails->ui.m_cmbParentCategory->currentData().value<RootItem*>();
auto* root = qobject_cast<TtRssServiceRoot*>(parent->getParentServiceRoot());
const int category_id = parent->kind() == RootItem::Kind::ServiceRoot ? 0 : parent->customId().toInt();
const int category_id = parent->kind() == RootItem::Kind::ServiceRoot ? 0 : parent->customNumericId();
const TtRssSubscribeToFeedResponse response =
root->network()->subscribeToFeed(m_feedDetails->ui.m_txtUrl->lineEdit()->text(),
category_id,
@ -66,11 +66,6 @@ void FormTtRssFeedDetails::loadFeedData() {
if (!m_urlToProcess.isEmpty()) {
m_feedDetails->ui.m_txtUrl->lineEdit()->setText(m_urlToProcess);
}
/*
else if (Application::clipboard()->mimeData()->hasText()) {
m_feedDetails->ui.m_txtUrl->lineEdit()->setText(Application::clipboard()->text());
}
*/
m_feedDetails->ui.m_txtUrl->lineEdit()->selectAll();
m_feedDetails->ui.m_txtUrl->setFocus();

View File

@ -11,8 +11,10 @@ class AuthenticationDetails;
class FormTtRssFeedDetails : public FormFeedDetails {
public:
explicit FormTtRssFeedDetails(ServiceRoot* service_root, RootItem* parent_to_select = nullptr,
const QString& url = QString(), QWidget* parent = nullptr);
explicit FormTtRssFeedDetails(ServiceRoot* service_root,
RootItem* parent_to_select = nullptr,
const QString& url = QString(),
QWidget* parent = nullptr);
protected slots:
virtual void apply();