refactor: introduce store for application state
The 'Store' is a convenient wrapper for injecting a dependency on the entire application state (root) so it can be re-used by independent flows of C++ logic. It will be used both to provide data to the view models for the QML UI, and as a way to record results of actions dispatched from the UI. With this change the following (additional) state is defined: - OverviewState, which will be used to track state that determines how the AccountsOverview QML UI should render and what features are enabled/disabled in it. This state may be manipulated as a a side-effect of various interactios with arbitrary pages. - FlowState, which will be used to track state about which control/ logic flows have completed and whether or not something is currently running. This is will be used to avoid distracting the user from an active UX flow with random unrelated prompts.master
parent
131e59aa3a
commit
bdcdb85bb6
|
@ -6,6 +6,7 @@
|
|||
set(keysmith_SRCS
|
||||
keysmith.cpp
|
||||
cli.cpp
|
||||
state_p.cpp
|
||||
)
|
||||
|
||||
add_library(keysmith_lib STATIC ${keysmith_SRCS})
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "keysmith.h"
|
||||
#include "../logging_p.h"
|
||||
|
||||
#include "state_p.h"
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QGuiApplication>
|
||||
|
||||
|
@ -52,16 +54,53 @@ namespace app
|
|||
Q_EMIT pushed(route, modelToTransfer);
|
||||
}
|
||||
|
||||
Keysmith::Keysmith(Navigation *navigation, QObject *parent): QObject(parent), m_navigation(navigation), m_storage(nullptr)
|
||||
static accounts::AccountStorage * openStorage(void)
|
||||
{
|
||||
qCDebug(logger) << "Initialising Keysmith account storage...";
|
||||
const accounts::SettingsProvider settings([](const accounts::PersistenceAction &action) -> void
|
||||
{
|
||||
QSettings data(QStringLiteral("org.kde.keysmith"), QStringLiteral("Keysmith"));
|
||||
action(data);
|
||||
});
|
||||
return accounts::AccountStorage::open(settings);
|
||||
}
|
||||
|
||||
Store::Store(void) :
|
||||
m_flows(QSharedPointer<FlowState>(new FlowState(), &QObject::deleteLater)),
|
||||
m_overview(QSharedPointer<OverviewState>(new OverviewState(), &QObject::deleteLater)),
|
||||
m_accounts(QSharedPointer<accounts::AccountStorage>(openStorage(), &accounts::AccountStorage::dispose)),
|
||||
m_accountList(QSharedPointer<model::SimpleAccountListModel>(nullptr, &QObject::deleteLater))
|
||||
{
|
||||
m_accountList.reset(new model::SimpleAccountListModel(m_accounts.data()));
|
||||
}
|
||||
|
||||
FlowState * Store::flows(void) const
|
||||
{
|
||||
return m_flows.data();
|
||||
}
|
||||
|
||||
OverviewState * Store::overview(void) const
|
||||
{
|
||||
return m_overview.data();
|
||||
}
|
||||
|
||||
accounts::AccountStorage * Store::accounts(void) const
|
||||
{
|
||||
return m_accounts.data();
|
||||
}
|
||||
|
||||
model::SimpleAccountListModel * Store::accountList(void) const
|
||||
{
|
||||
return m_accountList.data();
|
||||
}
|
||||
|
||||
Keysmith::Keysmith(Navigation *navigation, QObject *parent): QObject(parent), m_store(), m_navigation(navigation)
|
||||
{
|
||||
}
|
||||
|
||||
Keysmith::~Keysmith()
|
||||
{
|
||||
qCDebug(logger) << "Tearing down Keysmith application; requesting disposal of account storage";
|
||||
if (m_storage) {
|
||||
m_storage->dispose();
|
||||
}
|
||||
qCDebug(logger) << "Tearing down Keysmith application; disposal of account storage should be requested";
|
||||
}
|
||||
|
||||
Navigation * Keysmith::navigation(void) const
|
||||
|
@ -69,6 +108,11 @@ namespace app
|
|||
return m_navigation;
|
||||
}
|
||||
|
||||
const Store & Keysmith::store(void) const
|
||||
{
|
||||
return m_store;
|
||||
};
|
||||
|
||||
void Keysmith::copyToClipboard(const QString &text)
|
||||
{
|
||||
QClipboard * clipboard = QGuiApplication::clipboard();
|
||||
|
@ -82,25 +126,11 @@ namespace app
|
|||
|
||||
model::SimpleAccountListModel * Keysmith::accountListModel(void)
|
||||
{
|
||||
return new model::SimpleAccountListModel(storage(), this);
|
||||
return new model::SimpleAccountListModel(m_store.accounts(), this);
|
||||
}
|
||||
|
||||
model::PasswordRequest * Keysmith::passwordRequest(void)
|
||||
{
|
||||
return new model::PasswordRequest(storage()->secret(), this);
|
||||
}
|
||||
|
||||
accounts::AccountStorage * Keysmith::storage(void)
|
||||
{
|
||||
if (!m_storage) {
|
||||
const accounts::SettingsProvider settings([](const accounts::PersistenceAction &action) -> void
|
||||
{
|
||||
QSettings data(QStringLiteral("org.kde.keysmith"), QStringLiteral("Keysmith"));
|
||||
action(data);
|
||||
});
|
||||
m_storage = accounts::AccountStorage::open(settings);
|
||||
}
|
||||
|
||||
return m_storage;
|
||||
return new model::PasswordRequest(m_store.accounts()->secret(), this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <QMetaEnum>
|
||||
#include <QObject>
|
||||
#include <QQmlEngine>
|
||||
#include <QSharedPointer>
|
||||
|
||||
namespace app
|
||||
{
|
||||
|
@ -42,6 +43,24 @@ namespace app
|
|||
QQmlEngine * const m_engine;
|
||||
};
|
||||
|
||||
class OverviewState;
|
||||
class FlowState;
|
||||
|
||||
class Store
|
||||
{
|
||||
public:
|
||||
explicit Store(void);
|
||||
accounts::AccountStorage * accounts(void) const;
|
||||
model::SimpleAccountListModel * accountList(void) const;
|
||||
OverviewState * overview(void) const;
|
||||
FlowState * flows(void) const;
|
||||
private:
|
||||
QSharedPointer<FlowState> m_flows;
|
||||
QSharedPointer<OverviewState> m_overview;
|
||||
QSharedPointer<accounts::AccountStorage> m_accounts;
|
||||
QSharedPointer<model::SimpleAccountListModel> m_accountList;
|
||||
};
|
||||
|
||||
class Keysmith: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -49,6 +68,7 @@ namespace app
|
|||
public:
|
||||
explicit Keysmith(Navigation * const navigation, QObject *parent = nullptr);
|
||||
virtual ~Keysmith();
|
||||
const Store & store(void) const;
|
||||
Navigation * navigation(void) const;
|
||||
Q_INVOKABLE void copyToClipboard(const QString &text);
|
||||
Q_INVOKABLE model::SimpleAccountListModel * accountListModel(void);
|
||||
|
@ -56,8 +76,8 @@ namespace app
|
|||
private:
|
||||
accounts::AccountStorage * storage(void);
|
||||
private:
|
||||
Store m_store;
|
||||
Navigation * const m_navigation;
|
||||
accounts::AccountStorage *m_storage;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* SPDX-FileCopyrightText: 2021 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
||||
*/
|
||||
|
||||
#include "state_p.h"
|
||||
|
||||
namespace app
|
||||
{
|
||||
|
||||
OverviewState::OverviewState(QObject *parent) :
|
||||
QObject(parent), m_actionsEnabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool OverviewState::actionsEnabled(void) const
|
||||
{
|
||||
return m_actionsEnabled;
|
||||
}
|
||||
|
||||
void OverviewState::setActionsEnabled(bool enabled)
|
||||
{
|
||||
if (m_actionsEnabled != enabled) {
|
||||
m_actionsEnabled = enabled;
|
||||
Q_EMIT actionsEnabledChanged();
|
||||
}
|
||||
}
|
||||
|
||||
FlowState::FlowState(QObject *parent) :
|
||||
QObject(parent), m_flowRunning(false), m_initialFlowDone(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool FlowState::flowRunning(void) const
|
||||
{
|
||||
return m_flowRunning;
|
||||
}
|
||||
|
||||
void FlowState::setFlowRunning(bool running)
|
||||
{
|
||||
if (m_flowRunning != running) {
|
||||
m_flowRunning = running;
|
||||
Q_EMIT flowRunningChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool FlowState::initialFlowDone(void) const
|
||||
{
|
||||
return m_initialFlowDone;
|
||||
}
|
||||
|
||||
void FlowState::setInitialFlowDone(bool done)
|
||||
{
|
||||
if (m_initialFlowDone != done) {
|
||||
m_initialFlowDone = done;
|
||||
Q_EMIT initialFlowDoneChanged();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* SPDX-FileCopyrightText: 2021 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
||||
*/
|
||||
#ifndef APP_STATE_P_H
|
||||
#define APP_STATE_P_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace app
|
||||
{
|
||||
class OverviewState : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool actionsEnabled READ actionsEnabled WRITE setActionsEnabled NOTIFY actionsEnabledChanged)
|
||||
public:
|
||||
explicit OverviewState(QObject *parent = nullptr);
|
||||
bool actionsEnabled(void) const;
|
||||
void setActionsEnabled(bool enabled);
|
||||
Q_SIGNALS:
|
||||
void actionsEnabledChanged(void);
|
||||
private:
|
||||
bool m_actionsEnabled;
|
||||
};
|
||||
|
||||
class FlowState : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool initialFlowDone READ initialFlowDone WRITE setInitialFlowDone NOTIFY initialFlowDoneChanged)
|
||||
Q_PROPERTY(bool flowRunning READ flowRunning WRITE setFlowRunning NOTIFY flowRunningChanged)
|
||||
public:
|
||||
explicit FlowState(QObject *parent = nullptr);
|
||||
bool flowRunning(void) const;
|
||||
void setFlowRunning(bool running);
|
||||
bool initialFlowDone(void) const;
|
||||
void setInitialFlowDone(bool done);
|
||||
Q_SIGNALS:
|
||||
void initialFlowDoneChanged(void);
|
||||
void flowRunningChanged(void);
|
||||
private:
|
||||
bool m_flowRunning;
|
||||
bool m_initialFlowDone;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue