some more thoughts about state management

This commit is contained in:
Blue 2023-12-26 20:31:55 -03:00
parent 437e76067f
commit b38ed2107b
Signed by: blue
GPG key ID: 9B203B252A63EE38
13 changed files with 125 additions and 13 deletions

View file

@ -1,11 +1,13 @@
set(HEADERS
api.h
codes.h
finalaction.h
)
set(SOURCES
api.cpp
codes.cpp
finalaction.cpp
)
target_sources(magpie PRIVATE ${SOURCES})

View file

@ -3,8 +3,10 @@
#include <QJsonDocument>
#include <QJsonObject>
#include <QUrlQuery>
#include <QTimer>
#include "codes.h"
#include "finalaction.h"
constexpr const char* json = "application/json";
constexpr const char* urlEncoded = "application/x-www-form-urlencoded";
@ -15,7 +17,7 @@ const std::map<QString, QMetaType::Type> testStructure({
});
const std::map<QString, QMetaType::Type> resultStructure({
{"result", QMetaType::Double},
{"result", QMetaType::LongLong},
});
const std::map<QString, QMetaType::Type> tokensStructure({
@ -47,8 +49,12 @@ API::State API::getState() const {
void API::setTokens(const QString access, const QString &renew) {
accessToken = access;
renewToken = renew;
state = Authenticating;
emit stateChanged(state);
setState(Authenticating);
//dont forget to remove
QTimer::singleShot(1000, this, [this] () {
setState(Authenticated);
});
}
void API::setAddress(const QUrl& path) {
@ -60,10 +66,8 @@ void API::setAddress(const QUrl& path) {
}
address = path;
state = address.isEmpty() ? NoServer : NotAuthenticated;
emit addressChanged(address);
emit stateChanged(state);
setState(address.isEmpty() ? NoServer : NotAuthenticated);
}
std::optional<QVariantMap> API::readResult(QNetworkReply* reply) {
@ -100,6 +104,14 @@ bool API::validateResponse(const std::optional<QVariantMap>& data, const std::ma
return true;
}
void API::setState(State newState) {
if (newState == state)
return;
state = newState;
emit stateChanged(state);
}
void API::test(const QString& path, const QJSValue& finished) {
qDebug() << "Testing" << path;
if (state == Offline)
@ -177,7 +189,7 @@ void API::sendLogin(const QString& login, const QString& password, const QJSValu
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, urlEncoded);
setState(Authenticating);
QNetworkReply* reply = network.post(request, params.toString(QUrl::FullyEncoded).toUtf8());
connect(reply, &QNetworkReply::finished,
std::bind(&API::onLoginFinished, this, reply, finished)
@ -208,6 +220,11 @@ void API::onRegisterFinished(QNetworkReply* reply, const QJSValue& finished) con
}
void API::onLoginFinished(QNetworkReply* reply, const QJSValue& finished) {
State state = NotAuthenticated;
FinalAction action([this, &state]() { //this should be executed on leaving the function in any way
setState(state); //setting the state as a result of this object destruction
}); //this way any error will result in NotAuthenticated, and on success it should be Authenticated
std::unique_ptr<QNetworkReply, NetworkReplyDeleter> rpl(reply);
QNetworkReply::NetworkError error = reply->error();
std::optional<QVariantMap> data = readResult(reply);
@ -237,7 +254,6 @@ void API::onLoginFinished(QNetworkReply* reply, const QJSValue& finished) {
accessToken = data->value("accessToken").toString();
renewToken = data->value("renewToken").toString();
emit storeTokens(accessToken, renewToken);
emit stateChanged(state);
}
void API::callCallback(const QJSValue& callback, const QString& error, const QJSValueList& arguments) const {

View file

@ -57,6 +57,7 @@ private:
void setAddress(const QUrl& path);
static std::optional<QVariantMap> readResult(QNetworkReply* reply);
static bool validateResponse(const std::optional<QVariantMap>& data, const std::map<QString, QMetaType::Type>& structure);
void setState(State newState);
private:
QUrl address;

10
API/finalaction.cpp Normal file
View file

@ -0,0 +1,10 @@
#include "finalaction.h"
FinalAction::FinalAction(const std::function<void()>& action):
action(action)
{}
FinalAction::~FinalAction() {
action();
}

19
API/finalaction.h Normal file
View file

@ -0,0 +1,19 @@
#pragma once
#include <functional>
class FinalAction {
public:
FinalAction(const std::function<void()>& action);
~FinalAction();
FinalAction() = delete;
FinalAction(const FinalAction&) = delete;
FinalAction(FinalAction&&) = delete;
FinalAction& operator = (const FinalAction&) = delete;
FinalAction& operator = (FinalAction&&) = delete;
private:
std::function<void()> action;
};