From 374eaf966835048cfa9adcdd3450ec69bece8ede Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Fri, 15 Dec 2023 12:10:13 +0100 Subject: [PATCH] changelog --- resources/text/CHANGELOG | 21 +++++ .../gui/mediaplayer/libmpv/libmpvbackend.cpp | 1 + src/librssguard/network-web/apiserver.cpp | 85 +++++++++++++++---- src/librssguard/network-web/apiserver.h | 6 +- 4 files changed, 96 insertions(+), 17 deletions(-) diff --git a/resources/text/CHANGELOG b/resources/text/CHANGELOG index 4734fd6f3..ad6c61a6c 100644 --- a/resources/text/CHANGELOG +++ b/resources/text/CHANGELOG @@ -1,3 +1,24 @@ +4.6.3 +----- + +Dear users, there are new features which will be introduced in one of coming releases. + +First of them is built-in HTTP API server which will provide basic REST-like interface for working with RSS Guard - getting list of articles, marking articles read or unread, etc. This will allow to use RSS Guard as a article server in local network. + +In cooperation with the above feature, new "magazine view" will be implemented. This magazine view will be launchable even completely separately from RSS Guard in web browser and will be able to act as very simple web-based feed/article reader. It will fetch data directly from RSS Guard via its new web API and will display articles including their thumbnails in cool way. This feature will be also expanded in the future, based on user feedback. + +Added: +* Lite internal web browser now properly decodes all HTML pages according to their declared encoding. (9c7f55094) +* Image downscaling in lite browser is faster. (8b91d4709) +* Icon for classic RSS/ATOM accounts is now changeable. (#695) +* If main window is active then "fetching started" notifications are not delivered. (#597) +* Number of child feed/categories is now shown for each category. (#1183) + +Fixed: +* MPV libs were moved to separate Git submodule. (#1250) +* Applied workaround to fix PC not sleeping after sound is played. (#1118) +* Fixed problem with disappearing tabs. + 4.6.2 ----- diff --git a/src/librssguard/gui/mediaplayer/libmpv/libmpvbackend.cpp b/src/librssguard/gui/mediaplayer/libmpv/libmpvbackend.cpp index ad108953e..aa11e3417 100644 --- a/src/librssguard/gui/mediaplayer/libmpv/libmpvbackend.cpp +++ b/src/librssguard/gui/mediaplayer/libmpv/libmpvbackend.cpp @@ -78,6 +78,7 @@ LibMpvBackend::LibMpvBackend(Application* app, QWidget* parent) mpv_set_option_string(m_mpvHandle, "msg-level", "all=v"); mpv_set_option_string(m_mpvHandle, "config", "yes"); mpv_set_option_string(m_mpvHandle, "force-window", "yes"); + mpv_set_option_string(m_mpvHandle, "script-opts", "osc-idlescreen=no"); mpv_set_option_string(m_mpvHandle, "hwdec", "auto"); mpv_set_option_string(m_mpvHandle, "osd-playing-msg", "${media-title}"); mpv_set_option_string(m_mpvHandle, "osc", "yes"); diff --git a/src/librssguard/network-web/apiserver.cpp b/src/librssguard/network-web/apiserver.cpp index b3f68c930..7696729f8 100644 --- a/src/librssguard/network-web/apiserver.cpp +++ b/src/librssguard/network-web/apiserver.cpp @@ -1,4 +1,5 @@ -// For license of this file, see /LICENSE.md. +// For license of this file, see +// /LICENSE.md. #include "network-web/apiserver.h" @@ -49,9 +50,15 @@ void ApiServer::answerClient(QTcpSocket* socket, const HttpRequest& request) { } reply_message = generateHttpAnswer(200, - {{QSL("Access-Control-Allow-Origin"), QSL("*")}, - {QSL("Access-Control-Allow-Headers"), QSL("*")}, - {QSL("Content-Type"), QSL("application/json; charset=\"utf-8\"")}}, + {{QSL("Access-Control-Allow-" + "Origin"), + QSL("*")}, + {QSL("Access-Control-Allow-" + "Headers"), + QSL("*")}, + {QSL("Content-Type"), + QSL("application/json; " + "charset=\"utf-8\"")}}, json_data); #if !defined(NDEBUG) @@ -65,9 +72,16 @@ void ApiServer::answerClient(QTcpSocket* socket, const HttpRequest& request) { QByteArray ApiServer::processCorsPreflight() const { return generateHttpAnswer(204, - {{QSL("Access-Control-Allow-Origin"), QSL("*")}, - {QSL("Access-Control-Allow-Headers"), QSL("*")}, - {QSL("Access-Control-Allow-Methods"), QSL("POST, GET, OPTIONS, DELETE")}}); + {{QSL("Access-Control-Allow-" + "Origin"), + QSL("*")}, + {QSL("Access-Control-Allow-" + "Headers"), + QSL("*")}, + {QSL("Access-Control-Allow-" + "Methods"), + QSL("POST, GET, OPTIONS, " + "DELETE")}}); } QByteArray ApiServer::processHtmlPage() const { @@ -82,10 +96,19 @@ QByteArray ApiServer::processHtmlPage() const { } QByteArray data = generateHttpAnswer(200, - {{QSL("Access-Control-Allow-Origin"), QSL("*")}, - {QSL("Access-Control-Allow-Headers"), QSL("*")}, - {QSL("Access-Control-Allow-Methods"), QSL("POST, GET, OPTIONS, DELETE")}, - {QSL("Content-Type"), QSL("text/html; charset=\"utf-8\"")}}, + {{QSL("Access-Control-Allow-" + "Origin"), + QSL("*")}, + {QSL("Access-Control-Allow-" + "Headers"), + QSL("*")}, + {QSL("Access-Control-Allow-" + "Methods"), + QSL("POST, GET, OPTIONS, " + "DELETE")}, + {QSL("Content-Type"), + QSL("text/html; " + "charset=\"utf-8\"")}}, page); return data; @@ -109,11 +132,35 @@ ApiResponse ApiServer::processAppVersion() const { return ApiResponse(ApiResponse::Result::Success, ApiRequest::Method::AppVersion, QSL(APP_VERSION)); } +ApiResponse ApiServer::processMarkArticles(const QJsonValue& req) const { + QJsonObject data = req.toObject(); + + bool mark_read = data.value(QSL("mark_read")).toBool(); + bool mark_unread = data.value(QSL("mark_unread")).toBool(); + bool mark_starred = data.value(QSL("mark_starred")).toBool(); + bool mark_unstarred = data.value(QSL("mark_unstarred")).toBool(); + + QMap articles_per_accounts; + + for (const QJsonValue& article_val : data.value(QSL("articles")).toArray()) { + QJsonObject article_obj = article_val.toObject(); + + articles_per_accounts[article_obj.value(QSL("accountId")).toInt()].append(article_obj.value(QSL("article_custom_id")).toString(); + } + + ApiResponse resp(ApiResponse::Result::Success, ApiRequest::Method::MarkArticles); + + return resp; +} + ApiResponse ApiServer::processArticlesFromFeed(const QJsonValue& req) const { QJsonObject data = req.toObject(); QString feed_id = data.value(QSL("feed")).toString(); - qint64 start_after_article_date = qint64(data.value(QSL("start_after_article_date")).toDouble()); + qint64 start_after_article_date = qint64(data + .value(QSL("start_after_" + "article_date")) + .toDouble()); int account_id = data.value(QSL("account")).toInt(); bool newest_first = data.value(QSL("newest_first")).toBool(); bool unread_only = data.value(QSL("unread_only")).toBool(); @@ -148,7 +195,10 @@ ApiResponse ApiServer::processArticlesFromFeed(const QJsonValue& req) const { } ApiResponse ApiServer::processUnknown() const { - return ApiResponse(ApiResponse::Result::Error, ApiRequest::Method::Unknown, QSL("unknown method")); + return ApiResponse(ApiResponse::Result::Error, + ApiRequest::Method::Unknown, + QSL("unknown " + "method")); } ApiResponse::ApiResponse(Result result, ApiRequest::Method method, const QJsonValue& response) @@ -162,12 +212,17 @@ QJsonDocument ApiResponse::toJson() const { obj.insert(QSL("method"), enumer_method.valueToKey(int(m_method))); obj.insert(QSL("result"), enumer_result.valueToKey(int(m_result))); - obj.insert(QSL("data"), m_response); + + if (!m_response.isNull() && !m_response.isUndefined()) { + obj.insert(QSL("data"), m_response); + } return QJsonDocument(obj); } -ApiRequest::ApiRequest(const QJsonDocument& data) : m_method(), m_parameters(data.object().value(QSL("data"))) { +ApiRequest::ApiRequest(const QJsonDocument& data) + : m_method(), m_parameters(data.object().value(QSL("dat" + "a"))) { static QMetaEnum enumer = QMetaEnum::fromType(); QByteArray method_name = data.object().value(QSL("method")).toString().toLocal8Bit(); diff --git a/src/librssguard/network-web/apiserver.h b/src/librssguard/network-web/apiserver.h index 54a1a9e32..9b75eb9b2 100644 --- a/src/librssguard/network-web/apiserver.h +++ b/src/librssguard/network-web/apiserver.h @@ -15,7 +15,8 @@ struct ApiRequest { enum class Method { Unknown = 0, AppVersion = 1, - ArticlesFromFeed = 2 + ArticlesFromFeed = 2, + MarkArticles = 3 }; Q_ENUM(Method) @@ -37,7 +38,7 @@ struct ApiResponse { Q_ENUM(Result) - explicit ApiResponse(Result result, ApiRequest::Method method, const QJsonValue& response); + explicit ApiResponse(Result result, ApiRequest::Method method, const QJsonValue& response = {}); Result m_result; ApiRequest::Method m_method; @@ -61,6 +62,7 @@ class ApiServer : public HttpServer { ApiResponse processAppVersion() const; ApiResponse processArticlesFromFeed(const QJsonValue& req) const; ApiResponse processUnknown() const; + ApiResponse processMarkArticles(const QJsonValue& req) const; }; #endif // APISERVER_H