From 86196cfd628397281ed342a17e9059bafc4f0385 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 17 Sep 2019 18:39:31 -0700 Subject: [PATCH 1/3] Add account settings to the AccountManager --- libraries/networking/src/AccountManager.cpp | 128 +++++++++++++++---- libraries/networking/src/AccountManager.h | 22 +++- libraries/networking/src/AccountSettings.cpp | 83 ++++++++++++ libraries/networking/src/AccountSettings.h | 59 +++++++++ 4 files changed, 261 insertions(+), 31 deletions(-) create mode 100644 libraries/networking/src/AccountSettings.cpp create mode 100644 libraries/networking/src/AccountSettings.h diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index a27d89e678..ab8dfd5ed9 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -87,6 +87,14 @@ AccountManager::AccountManager(UserAgentGetter userAgentGetter) : qRegisterMetaType(); connect(this, &AccountManager::loginComplete, this, &AccountManager::uploadPublicKey); + connect(this, &AccountManager::loginComplete, this, &AccountManager::requestAccountSettings); + + static int POST_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; + _postSettingsTimer = new QTimer(this); + _postSettingsTimer->setInterval(POST_SETTINGS_INTERVAL); + connect(this, SIGNAL(loginComplete(QUrl)), _postSettingsTimer, SLOT(start())); + connect(this, &AccountManager::logoutComplete, _postSettingsTimer, &QTimer::stop); + connect(_postSettingsTimer, &QTimer::timeout, this, &AccountManager::postAccountSettings); } const QString DOUBLE_SLASH_SUBSTITUTE = "slashslash"; @@ -160,33 +168,7 @@ void AccountManager::setAuthURL(const QUrl& authURL) { qCDebug(networking) << "Found metaverse API account information for" << qPrintable(_authURL.toString()); } else { - // we didn't have a file - see if we can migrate old settings and store them in the new file - - // check if there are existing access tokens to load from settings - Settings settings; - settings.beginGroup(ACCOUNTS_GROUP); - - foreach(const QString& key, settings.allKeys()) { - // take a key copy to perform the double slash replacement - QString keyCopy(key); - QUrl keyURL(keyCopy.replace(DOUBLE_SLASH_SUBSTITUTE, "//")); - - if (keyURL == _authURL) { - // pull out the stored access token and store it in memory - _accountInfo = settings.value(key).value(); - - qCDebug(networking) << "Migrated an access token for" << qPrintable(keyURL.toString()) - << "from previous settings file"; - } - } - settings.endGroup(); - - if (_accountInfo.getAccessToken().token.isEmpty()) { - qCWarning(networking) << "Unable to load account file. No existing account settings will be loaded."; - } else { - // persist the migrated settings to file - persistAccountToFile(); - } + qCWarning(networking) << "Unable to load account file. No existing account settings will be loaded."; } if (_isAgent && !_accountInfo.getAccessToken().token.isEmpty() && !_accountInfo.hasProfile()) { @@ -199,6 +181,10 @@ void AccountManager::setAuthURL(const QUrl& authURL) { refreshAccessToken(); } + if (isLoggedIn()) { + emit loginComplete(_authURL); + } + // tell listeners that the auth endpoint has changed emit authEndpointChanged(); } @@ -804,6 +790,94 @@ void AccountManager::requestProfileError(QNetworkReply::NetworkError error) { qCDebug(networking) << "AccountManager requestProfileError - " << error; } +void AccountManager::requestAccountSettings() { + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + + QUrl lockerURL = _authURL; + lockerURL.setPath("/api/v1/user/locker"); + + QNetworkRequest lockerRequest(lockerURL); + lockerRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + lockerRequest.setHeader(QNetworkRequest::UserAgentHeader, _userAgentGetter()); + lockerRequest.setRawHeader(ACCESS_TOKEN_AUTHORIZATION_HEADER, _accountInfo.getAccessToken().authorizationHeaderValue()); + + QNetworkReply* lockerReply = networkAccessManager.get(lockerRequest); + connect(lockerReply, &QNetworkReply::finished, this, &AccountManager::requestAccountSettingsFinished); + connect(lockerReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccountSettingsError(QNetworkReply::NetworkError))); +} + +void AccountManager::requestAccountSettingsFinished() { + QNetworkReply* lockerReply = reinterpret_cast(sender()); + + QJsonDocument jsonResponse = QJsonDocument::fromJson(lockerReply->readAll()); + const QJsonObject& rootObject = jsonResponse.object(); + + if (rootObject.contains("status") && rootObject["status"].toString() == "success") { + if (rootObject.contains("data") && rootObject["data"].isObject()) { + _settings.unpack(rootObject["data"].toObject()); + + emit accountSettingsLoaded(); + } else { + qCDebug(networking) << "Error in response for account settings: no data object"; + } + } else { + // TODO: error handling + qCDebug(networking) << "Error in response for account settings" << lockerReply->errorString(); + } +} + +void AccountManager::requestAccountSettingsError(QNetworkReply::NetworkError error) { + // TODO: error handling + qCWarning(networking) << "Account settings request encountered an error" << error; +} + +void AccountManager::postAccountSettings() { + if (!_settings.somethingChanged()) { + // Nothing changed, skipping settings post + return; + } + if (!isLoggedIn()) { + qCWarning(networking) << "Can't post account settings: Not logged in"; + } + + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + + QUrl lockerURL = _authURL; + lockerURL.setPath("/api/v1/user/locker"); + + QNetworkRequest lockerRequest(lockerURL); + lockerRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + lockerRequest.setHeader(QNetworkRequest::UserAgentHeader, _userAgentGetter()); + lockerRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + lockerRequest.setRawHeader(ACCESS_TOKEN_AUTHORIZATION_HEADER, _accountInfo.getAccessToken().authorizationHeaderValue()); + + QJsonObject dataObj; + dataObj.insert("locker", _settings.pack()); + + auto postData = QJsonDocument(dataObj).toJson(QJsonDocument::Compact); + + QNetworkReply* lockerReply = networkAccessManager.put(lockerRequest, postData); + connect(lockerReply, &QNetworkReply::finished, this, &AccountManager::postAccountSettingsFinished); + connect(lockerReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(postAccountSettingsError(QNetworkReply::NetworkError))); +} + +void AccountManager::postAccountSettingsFinished() { + QNetworkReply* lockerReply = reinterpret_cast(sender()); + + QJsonDocument jsonResponse = QJsonDocument::fromJson(lockerReply->readAll()); + const QJsonObject& rootObject = jsonResponse.object(); + + if (!rootObject.contains("status") || rootObject["status"].toString() != "success") { + // TODO: error handling + qCDebug(networking) << "Error in response for account settings post" << lockerReply->errorString(); + } +} + +void AccountManager::postAccountSettingsError(QNetworkReply::NetworkError error) { + // TODO: error handling + qCWarning(networking) << "Post encountered an error" << error; +} + void AccountManager::generateNewKeypair(bool isUserKeypair, const QUuid& domainID) { if (thread() != QThread::currentThread()) { diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index a88a5cc4e7..a5ff2ee100 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -14,18 +14,19 @@ #include #include +#include #include #include #include +#include + +#include "AccountSettings.h" +#include "DataServerAccountInfo.h" #include "NetworkingConstants.h" #include "NetworkAccessManager.h" - -#include "DataServerAccountInfo.h" #include "SharedUtil.h" -#include - class JSONCallbackParameters { public: JSONCallbackParameters(QObject* callbackReceiver = nullptr, @@ -107,6 +108,8 @@ public: void setConfigFileURL(const QString& fileURL) { _configFileURL = fileURL; } void saveLoginStatus(bool isLoggedIn); + AccountSettings& getAccountSettings() { return _settings; } + public slots: void requestAccessToken(const QString& login, const QString& password); void requestAccessTokenWithSteam(QByteArray authSessionTicket); @@ -136,6 +139,7 @@ signals: void logoutComplete(); void newKeypair(); void limitedCommerceChanged(); + void accountSettingsLoaded(); private slots: void handleKeypairGenerationError(); @@ -145,6 +149,13 @@ private slots: void publicKeyUploadFailed(QNetworkReply* reply); void generateNewKeypair(bool isUserKeypair = true, const QUuid& domainID = QUuid()); + void requestAccountSettings(); + void requestAccountSettingsFinished(); + void requestAccountSettingsError(QNetworkReply::NetworkError error); + void postAccountSettings(); + void postAccountSettingsFinished(); + void postAccountSettingsError(QNetworkReply::NetworkError error); + private: AccountManager(AccountManager const& other) = delete; void operator=(AccountManager const& other) = delete; @@ -170,6 +181,9 @@ private: bool _limitedCommerce { false }; QString _configFileURL; + + AccountSettings _settings; + QTimer* _postSettingsTimer; }; #endif // hifi_AccountManager_h diff --git a/libraries/networking/src/AccountSettings.cpp b/libraries/networking/src/AccountSettings.cpp new file mode 100644 index 0000000000..ac6f54b40a --- /dev/null +++ b/libraries/networking/src/AccountSettings.cpp @@ -0,0 +1,83 @@ +// +// AccountSettings.cpp +// libraries/networking/src +// +// Created by Clement Brisset on 9/12/19. +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "AccountSettings.h" + +#include +#include + +#include "NetworkLogging.h" + +// Examples: +//static QString SOME_STRING_KEY { "some_string" }; +//static QString SOME_INT_KEY { "some_int" }; +//static QString SOME_BOOL_KEY { "some_bool" }; + +// Examples: +//QString AccountSettings::DEFAULT_SOME_STRING { "" }; +//int AccountSettings::DEFAULT_SOME_INT { 17 }; +//bool AccountSettings::DEFAULT_SOME_BOOL { true }; + +QJsonObject AccountSettings::pack() { + QJsonObject data; + + QReadLocker lock(&_settingsLock); +// Examples: +// data.insert(SOME_STRING_KEY, _someString); +// data.insert(SOME_INT_KEY, _someInt); +// data.insert(SOME_BOOL_KEY, _someBool); + + return data; +} + +void AccountSettings::unpack(QJsonObject data) { + QWriteLocker lock(&_settingsLock); + +// Examples: +// auto it = data.find(SOME_STRING_KEY); +// _hasSomeString = it != data.end() && it->isString(); +// _someString = _hasSomeString ? it->toString() : DEFAULT_SOME_STRING; +// +// it = data.find(SOME_INT_KEY); +// _hasSomeInt = it != data.end() && it->isDouble(); +// _someInt = _hasSomeInt ? it->toInt() : DEFAULT_SOME_INT; +// +// it = data.find(SOME_BOOL_KEY); +// _hasSomeBool = it != data.end() && it->isBool(); +// _someBool = _hasSomeBool ? it->toBool() : DEFAULT_SOME_BOOL; + + _somethingChanged = false; +} + +// Examples: +//void AccountSettings::setSomeString(QString someString) { +// QWriteLocker lock(&_settingsLock); +// if (someString != _someString) { +// _somethingChanged = true; +// } +// _someString = someString; +//} +// +//void AccountSettings::setSomeInt(int someInt) { +// QWriteLocker lock(&_settingsLock); +// if (someInt != _someInt) { +// _somethingChanged = true; +// } +// _someInt = someInt; +//} +// +//void AccountSettings::setSomeBool(bool someBool) { +// QWriteLocker lock(&_settingsLock); +// if (someBool != _someBool) { +// _somethingChanged = true; +// } +// _someBool = someBool; +//} diff --git a/libraries/networking/src/AccountSettings.h b/libraries/networking/src/AccountSettings.h new file mode 100644 index 0000000000..4a5205bd30 --- /dev/null +++ b/libraries/networking/src/AccountSettings.h @@ -0,0 +1,59 @@ +// +// AccountSettings.h +// libraries/networking/src +// +// Created by Clement Brisset on 9/12/19. +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AccountSettings_h +#define hifi_AccountSettings_h + +#include +#include +#include + +class AccountSettings { +public: +// Examples: +// static QString DEFAULT_SOME_STRING; +// static int DEFAULT_SOME_INT; +// static bool DEFAULT_SOME_BOOL; + + bool somethingChanged() const { return _somethingChanged; } + + QJsonObject pack(); + void unpack(QJsonObject data); + +// Examples: +// bool hasSomeString() const { QReadLocker lock(&_settingsLock); return _hasSomeString; } +// QString getSomeString() const { QReadLocker lock(&_settingsLock); return _someString; } +// void setSomeString(QString someString); +// +// bool hasSomeInt() const { QReadLocker lock(&_settingsLock); return _hasSomeInt; } +// int getSomeInt() const { QReadLocker lock(&_settingsLock); return _someInt; } +// void setSomeInt(int someInt); +// +// bool hasSomeBool() const { QReadLocker lock(&_settingsLock); return _hasSomeBool; } +// bool getSomeBool() const { QReadLocker lock(&_settingsLock); return _someBool; } +// void setSomeBool(bool someBool); + +private: + mutable QReadWriteLock _settingsLock; + bool _somethingChanged { false }; + +// Examples: +// bool _hasSomeString { false }; +// bool _hasSomeInt { false }; +// bool _hasSomeBool { false }; + +// Examples: +// QString _someString { DEFAULT_SOME_STRING }; +// int _someInt { DEFAULT_SOME_INT }; +// bool _someBool { DEFAULT_SOME_BOOL }; +}; + +#endif /* hifi_AccountSettings_h */ From 282aa70db37df48c8c8bf1782ae7ce628a8a9dcc Mon Sep 17 00:00:00 2001 From: Clement Date: Thu, 19 Sep 2019 13:45:34 -0700 Subject: [PATCH 2/3] Sync settings on logout/shutdown --- libraries/networking/src/AccountManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index ab8dfd5ed9..4e6fd3afb7 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -95,12 +95,14 @@ AccountManager::AccountManager(UserAgentGetter userAgentGetter) : connect(this, SIGNAL(loginComplete(QUrl)), _postSettingsTimer, SLOT(start())); connect(this, &AccountManager::logoutComplete, _postSettingsTimer, &QTimer::stop); connect(_postSettingsTimer, &QTimer::timeout, this, &AccountManager::postAccountSettings); + connect(qApp, &QCoreApplication::aboutToQuit, this, &AccountManager::postAccountSettings); } const QString DOUBLE_SLASH_SUBSTITUTE = "slashslash"; const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner"; void AccountManager::logout() { + postAccountSettings(); // a logout means we want to delete the DataServerAccountInfo we currently have for this URL, in-memory and in file _accountInfo = DataServerAccountInfo(); From 1924dad51b27c8eea576468cd644a24366f6e985 Mon Sep 17 00:00:00 2001 From: Clement Date: Fri, 20 Sep 2019 13:11:05 -0700 Subject: [PATCH 3/3] CR changes --- libraries/networking/src/AccountManager.cpp | 24 ++++--- libraries/networking/src/AccountManager.h | 4 +- libraries/networking/src/AccountSettings.cpp | 72 ++++++-------------- libraries/networking/src/AccountSettings.h | 42 ++++-------- 4 files changed, 56 insertions(+), 86 deletions(-) diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 4e6fd3afb7..a31d117f59 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -47,6 +47,9 @@ Q_DECLARE_METATYPE(JSONCallbackParameters) const QString ACCOUNTS_GROUP = "accounts"; +const int POST_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; +const int PULL_SETTINGS_RETRY_INTERVAL = 1 * MSECS_PER_SECOND; + JSONCallbackParameters::JSONCallbackParameters(QObject* callbackReceiver, const QString& jsonCallbackMethod, const QString& errorCallbackMethod) : @@ -89,7 +92,6 @@ AccountManager::AccountManager(UserAgentGetter userAgentGetter) : connect(this, &AccountManager::loginComplete, this, &AccountManager::uploadPublicKey); connect(this, &AccountManager::loginComplete, this, &AccountManager::requestAccountSettings); - static int POST_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; _postSettingsTimer = new QTimer(this); _postSettingsTimer->setInterval(POST_SETTINGS_INTERVAL); connect(this, SIGNAL(loginComplete(QUrl)), _postSettingsTimer, SLOT(start())); @@ -98,7 +100,6 @@ AccountManager::AccountManager(UserAgentGetter userAgentGetter) : connect(qApp, &QCoreApplication::aboutToQuit, this, &AccountManager::postAccountSettings); } -const QString DOUBLE_SLASH_SUBSTITUTE = "slashslash"; const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner"; void AccountManager::logout() { @@ -114,6 +115,8 @@ void AccountManager::logout() { emit logoutComplete(); // the username has changed to blank emit usernameChanged(QString()); + + _settings.loggedOut(); } QString accountFileDir() { @@ -806,6 +809,8 @@ void AccountManager::requestAccountSettings() { QNetworkReply* lockerReply = networkAccessManager.get(lockerRequest); connect(lockerReply, &QNetworkReply::finished, this, &AccountManager::requestAccountSettingsFinished); connect(lockerReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccountSettingsError(QNetworkReply::NetworkError))); + + _settings.startedLoading(); } void AccountManager::requestAccountSettingsFinished() { @@ -821,25 +826,27 @@ void AccountManager::requestAccountSettingsFinished() { emit accountSettingsLoaded(); } else { qCDebug(networking) << "Error in response for account settings: no data object"; + QTimer::singleShot(PULL_SETTINGS_RETRY_INTERVAL, this, &AccountManager::requestAccountSettings); } } else { - // TODO: error handling qCDebug(networking) << "Error in response for account settings" << lockerReply->errorString(); + QTimer::singleShot(PULL_SETTINGS_RETRY_INTERVAL, this, &AccountManager::requestAccountSettings); } } void AccountManager::requestAccountSettingsError(QNetworkReply::NetworkError error) { - // TODO: error handling qCWarning(networking) << "Account settings request encountered an error" << error; + QTimer::singleShot(PULL_SETTINGS_RETRY_INTERVAL, this, &AccountManager::requestAccountSettings); } void AccountManager::postAccountSettings() { - if (!_settings.somethingChanged()) { + if (_settings.lastChangeTimestamp() <= _lastSuccessfulSyncTimestamp && _lastSuccessfulSyncTimestamp != 0) { // Nothing changed, skipping settings post return; } if (!isLoggedIn()) { qCWarning(networking) << "Can't post account settings: Not logged in"; + return; } QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); @@ -853,6 +860,7 @@ void AccountManager::postAccountSettings() { lockerRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); lockerRequest.setRawHeader(ACCESS_TOKEN_AUTHORIZATION_HEADER, _accountInfo.getAccessToken().authorizationHeaderValue()); + _currentSyncTimestamp = _settings.lastChangeTimestamp(); QJsonObject dataObj; dataObj.insert("locker", _settings.pack()); @@ -869,14 +877,14 @@ void AccountManager::postAccountSettingsFinished() { QJsonDocument jsonResponse = QJsonDocument::fromJson(lockerReply->readAll()); const QJsonObject& rootObject = jsonResponse.object(); - if (!rootObject.contains("status") || rootObject["status"].toString() != "success") { - // TODO: error handling + if (rootObject.contains("status") && rootObject["status"].toString() == "success") { + _lastSuccessfulSyncTimestamp = _currentSyncTimestamp; + } else { qCDebug(networking) << "Error in response for account settings post" << lockerReply->errorString(); } } void AccountManager::postAccountSettingsError(QNetworkReply::NetworkError error) { - // TODO: error handling qCWarning(networking) << "Post encountered an error" << error; } diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index a5ff2ee100..f29221d671 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -183,7 +183,9 @@ private: QString _configFileURL; AccountSettings _settings; - QTimer* _postSettingsTimer; + quint64 _currentSyncTimestamp { 0 }; + quint64 _lastSuccessfulSyncTimestamp { 0 }; + QTimer* _postSettingsTimer { nullptr }; }; #endif // hifi_AccountManager_h diff --git a/libraries/networking/src/AccountSettings.cpp b/libraries/networking/src/AccountSettings.cpp index ac6f54b40a..6562826dd7 100644 --- a/libraries/networking/src/AccountSettings.cpp +++ b/libraries/networking/src/AccountSettings.cpp @@ -15,25 +15,15 @@ #include #include "NetworkLogging.h" +#include "SharedUtil.h" -// Examples: -//static QString SOME_STRING_KEY { "some_string" }; -//static QString SOME_INT_KEY { "some_int" }; -//static QString SOME_BOOL_KEY { "some_bool" }; - -// Examples: -//QString AccountSettings::DEFAULT_SOME_STRING { "" }; -//int AccountSettings::DEFAULT_SOME_INT { 17 }; -//bool AccountSettings::DEFAULT_SOME_BOOL { true }; +static QString HOME_LOCATION_KEY { "home_location" }; QJsonObject AccountSettings::pack() { QJsonObject data; QReadLocker lock(&_settingsLock); -// Examples: -// data.insert(SOME_STRING_KEY, _someString); -// data.insert(SOME_INT_KEY, _someInt); -// data.insert(SOME_BOOL_KEY, _someBool); + data.insert(HOME_LOCATION_KEY, _homeLocation); return data; } @@ -41,43 +31,25 @@ QJsonObject AccountSettings::pack() { void AccountSettings::unpack(QJsonObject data) { QWriteLocker lock(&_settingsLock); -// Examples: -// auto it = data.find(SOME_STRING_KEY); -// _hasSomeString = it != data.end() && it->isString(); -// _someString = _hasSomeString ? it->toString() : DEFAULT_SOME_STRING; -// -// it = data.find(SOME_INT_KEY); -// _hasSomeInt = it != data.end() && it->isDouble(); -// _someInt = _hasSomeInt ? it->toInt() : DEFAULT_SOME_INT; -// -// it = data.find(SOME_BOOL_KEY); -// _hasSomeBool = it != data.end() && it->isBool(); -// _someBool = _hasSomeBool ? it->toBool() : DEFAULT_SOME_BOOL; + _lastChangeTimestamp = usecTimestampNow(); - _somethingChanged = false; + auto it = data.find(HOME_LOCATION_KEY); + _homeLocationState = it != data.end() && it->isString() ? Loaded : NotPresent; + _homeLocation = _homeLocationState == Loaded ? it->toString() : ""; } -// Examples: -//void AccountSettings::setSomeString(QString someString) { -// QWriteLocker lock(&_settingsLock); -// if (someString != _someString) { -// _somethingChanged = true; -// } -// _someString = someString; -//} -// -//void AccountSettings::setSomeInt(int someInt) { -// QWriteLocker lock(&_settingsLock); -// if (someInt != _someInt) { -// _somethingChanged = true; -// } -// _someInt = someInt; -//} -// -//void AccountSettings::setSomeBool(bool someBool) { -// QWriteLocker lock(&_settingsLock); -// if (someBool != _someBool) { -// _somethingChanged = true; -// } -// _someBool = someBool; -//} +void AccountSettings::setHomeLocation(QString homeLocation) { + QWriteLocker lock(&_settingsLock); + if (homeLocation != _homeLocation) { + _lastChangeTimestamp = usecTimestampNow(); + } + _homeLocation = homeLocation; +} + +void AccountSettings::startedLoading() { + _homeLocationState = Loading; +} + +void AccountSettings::loggedOut() { + _homeLocationState = LoggedOut; +} diff --git a/libraries/networking/src/AccountSettings.h b/libraries/networking/src/AccountSettings.h index 4a5205bd30..7bec5ce767 100644 --- a/libraries/networking/src/AccountSettings.h +++ b/libraries/networking/src/AccountSettings.h @@ -18,42 +18,30 @@ class AccountSettings { public: -// Examples: -// static QString DEFAULT_SOME_STRING; -// static int DEFAULT_SOME_INT; -// static bool DEFAULT_SOME_BOOL; + enum State { + LoggedOut, + Loading, + Loaded, + NotPresent + }; - bool somethingChanged() const { return _somethingChanged; } + void loggedOut(); + void startedLoading(); + quint64 lastChangeTimestamp() const { return _lastChangeTimestamp; } QJsonObject pack(); void unpack(QJsonObject data); -// Examples: -// bool hasSomeString() const { QReadLocker lock(&_settingsLock); return _hasSomeString; } -// QString getSomeString() const { QReadLocker lock(&_settingsLock); return _someString; } -// void setSomeString(QString someString); -// -// bool hasSomeInt() const { QReadLocker lock(&_settingsLock); return _hasSomeInt; } -// int getSomeInt() const { QReadLocker lock(&_settingsLock); return _someInt; } -// void setSomeInt(int someInt); -// -// bool hasSomeBool() const { QReadLocker lock(&_settingsLock); return _hasSomeBool; } -// bool getSomeBool() const { QReadLocker lock(&_settingsLock); return _someBool; } -// void setSomeBool(bool someBool); + State homeLocationState() const { QReadLocker lock(&_settingsLock); return _homeLocationState; } + QString getHomeLocation() const { QReadLocker lock(&_settingsLock); return _homeLocation; } + void setHomeLocation(QString homeLocation); private: mutable QReadWriteLock _settingsLock; - bool _somethingChanged { false }; + quint64 _lastChangeTimestamp { 0 }; -// Examples: -// bool _hasSomeString { false }; -// bool _hasSomeInt { false }; -// bool _hasSomeBool { false }; - -// Examples: -// QString _someString { DEFAULT_SOME_STRING }; -// int _someInt { DEFAULT_SOME_INT }; -// bool _someBool { DEFAULT_SOME_BOOL }; + State _homeLocationState { LoggedOut }; + QString _homeLocation; }; #endif /* hifi_AccountSettings_h */