Add UserStatus enum with the pre defined status.
authorCamila <hello@camila.codes>
Sun, 21 Mar 2021 19:55:21 +0000 (20:55 +0100)
committerCamila <hello@camila.codes>
Wed, 24 Mar 2021 14:41:31 +0000 (15:41 +0100)
- User QHash to map status strings and Status enum.

Signed-off-by: Camila <hello@camila.codes>
src/gui/accountstate.cpp
src/gui/accountstate.h
src/gui/tray/NotificationHandler.cpp
src/gui/tray/NotificationHandler.h
src/gui/tray/UserModel.cpp
src/gui/tray/UserModel.h
src/gui/userstatus.cpp
src/gui/userstatus.h
src/libsync/networkjobs.cpp
src/libsync/networkjobs.h

index bd548c6a8c8538a4e3c4955a5f872131adfdf958..ac5a21c98d3d8178faaa151dd67ec9c97c3438fe 100644 (file)
@@ -21,7 +21,6 @@
 #include "logger.h"
 #include "configfile.h"
 #include "ocsnavigationappsjob.h"
-#include "userstatus.h"
 
 #include <QSettings>
 #include <QTimer>
@@ -46,7 +45,7 @@ AccountState::AccountState(AccountPtr account)
     , _maintenanceToConnectedDelay(60000 + (qrand() % (4 * 60000))) // 1-5min delay
     , _remoteWipe(new RemoteWipe(_account))
     , _userStatus(new UserStatus(this))
-    , _notificationStatus("online")
+    , _isDesktopNotificationsAllowed(true)
 {
     qRegisterMetaType<AccountState *>("AccountState*");
 
@@ -128,7 +127,7 @@ void AccountState::setState(State state)
     emit stateChanged(_state);
 }
 
-QString AccountState::status() const
+UserStatus::Status AccountState::status() const
 {
     return _userStatus->status();
 }
@@ -223,14 +222,14 @@ void AccountState::setNavigationAppsEtagResponseHeader(const QByteArray &value)
     _navigationAppsEtagResponseHeader = value;
 }
 
-QString AccountState::notificationStatus() const
+bool AccountState::isDesktopNotificationsAllowed() const
 {
-    return _notificationStatus;
+    return _isDesktopNotificationsAllowed;
 }
 
-void AccountState::setNotificationStatus(const QString &status)
+void AccountState::setDesktopNotificationsAllowed(const bool isAllowed)
 {
-    _notificationStatus = status;
+    _isDesktopNotificationsAllowed = isAllowed;
 }
 
 void AccountState::checkConnectivity()
@@ -452,7 +451,7 @@ void AccountState::fetchNavigationApps(){
 
 void AccountState::fetchUserStatus() 
 {
-    connect(_userStatus, &UserStatus::fetchUserStatusFinished, this, &AccountState::userStatusChanged);
+    connect(_userStatus, &UserStatus::fetchUserStatusFinished, this, &AccountState::statusChanged);
     _userStatus->fetchUserStatus(_account);
 }
 
index 5995449063980e29c1ae79ad240fac74c89df9cd..59966f1313181bc8f58db165f8164c04b770a1b9 100644 (file)
@@ -21,6 +21,7 @@
 #include <QPointer>
 #include "connectionvalidator.h"
 #include "creds/abstractcredentials.h"
+#include "userstatus.h"
 #include <memory>
 
 class QSettings;
@@ -31,7 +32,6 @@ class AccountState;
 class Account;
 class AccountApp;
 class RemoteWipe;
-class UserStatus;
 
 using AccountStatePtr = QExplicitlySharedDataPointer<AccountState>;
 using AccountAppList = QList<AccountApp *>;
@@ -162,10 +162,10 @@ public:
     ///Asks for user credentials
     void handleInvalidCredentials();
 
-    /** Returns the user status (online, dnd, away, offline, invisible)
+    /** Returns the user status (Online, Dnd, Away, Offline, Invisible)
      *  https://gist.github.com/georgehrke/55a0412007f13be1551d1f9436a39675
     */
-    QString status() const;
+    UserStatus::Status status() const;
 
     /** Returns the user status Message (emoji + text)
     */
@@ -175,14 +175,14 @@ public:
     */
     QUrl statusIcon() const;
 
-    /** Returns the user status retrieved by the notificatons endpoint: dnd or online
+    /** Returns the notifications status retrieved by the notificatons endpoint
      *  https://github.com/nextcloud/desktop/issues/2318#issuecomment-680698429
     */
-    QString notificationStatus() const;
+    bool isDesktopNotificationsAllowed() const;
 
-    /** Set new user status retrieved by the notificatons endpoint: dnd or online
+    /** Set desktop notifications status retrieved by the notificatons endpoint
     */
-    void setNotificationStatus(const QString &status);
+    void setDesktopNotificationsAllowed(const bool isAllowed);
 
     /** Fetch the user status (status, icon, message)
     */
@@ -201,7 +201,7 @@ signals:
     void stateChanged(State state);
     void isConnectedChanged();
     void hasFetchedNavigationApps();
-    void userStatusChanged();
+    void statusChanged();
 
 protected Q_SLOTS:
     void slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList &errors);
@@ -252,7 +252,7 @@ private:
     AccountAppList _apps;
 
     UserStatus *_userStatus;
-    QString _notificationStatus;
+    bool _isDesktopNotificationsAllowed;
 };
 
 class AccountApp : public QObject
index 4207ef1b778282bb00210d1427e2e98e57ba5b8a..46700ec1e23b8b75010f302c3843a93b488148a4 100644 (file)
@@ -48,8 +48,8 @@ void ServerNotificationHandler::slotFetchNotifications()
         this, &ServerNotificationHandler::slotNotificationsReceived);
     QObject::connect(_notificationJob.data(), &JsonApiJob::etagResponseHeaderReceived,
         this, &ServerNotificationHandler::slotEtagResponseHeaderReceived);
-    QObject::connect(_notificationJob.data(), &JsonApiJob::desktopNotificationStatusReceived,
-            this, &ServerNotificationHandler::slotDesktopNotificationStatusReceived);
+    QObject::connect(_notificationJob.data(), &JsonApiJob::allowDesktopNotificationsChanged,
+            this, &ServerNotificationHandler::slotAllowDesktopNotificationsChanged);
     _notificationJob->setProperty(propertyAccountStateC, QVariant::fromValue<AccountState *>(_accountState));
     _notificationJob->addRawHeader("If-None-Match", _accountState->notificationsEtagResponseHeader());
     _notificationJob->start();
@@ -64,11 +64,11 @@ void ServerNotificationHandler::slotEtagResponseHeaderReceived(const QByteArray
     }
 }
 
-void ServerNotificationHandler::slotDesktopNotificationStatusReceived(const bool status)
+void ServerNotificationHandler::slotAllowDesktopNotificationsChanged(const bool isAllowed)
 {
     auto *account = qvariant_cast<AccountState *>(sender()->property(propertyAccountStateC));
     if (account != nullptr) {
-       account->setDesktopNotificationsStatus(status);
+       account->setDesktopNotificationsAllowed(isAllowed);
     }
 }
 
index a070ab6caf30543fbe61b5d2ae8b43aadea9d32b..61fbb51ec5dfd2140858a3ecbca9c21df3040ad8 100644 (file)
@@ -26,7 +26,7 @@ private slots:
     void slotNotificationsReceived(const QJsonDocument &json, int statusCode);
     void slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode);
     void slotIconDownloaded(QByteArray iconData);
-    void slotDesktopNotificationStatusReceived(const bool status);
+    void slotAllowDesktopNotificationsChanged(const bool isAllowed);
 
 private:
     QPointer<JsonApiJob> _notificationJob;
index 8ca2c2aa61c60941926076d69048ceac8e231913..3d29b522692b95caf332e297a405bd4b4f32d297 100644 (file)
@@ -53,7 +53,7 @@ User::User(AccountStatePtr &account, const bool &isCurrent, QObject *parent)
     connect(this, &User::guiLog, Logger::instance(), &Logger::guiLog);
 
     connect(_account->account().data(), &Account::accountChangedAvatar, this, &User::avatarChanged);
-    connect(_account.data(), &AccountState::userStatusChanged, this, &User::userStatusChanged);
+    connect(_account.data(), &AccountState::statusChanged, this, &User::statusChanged);
 
     connect(_activityModel, &ActivityListModel::sendNotificationRequest, this, &User::slotSendNotificationRequest);
 }
@@ -559,7 +559,7 @@ QString User::server(bool shortened) const
     return serverUrl;
 }
 
-QString User::status() const
+UserStatus::Status User::status() const
 {
     return _account->status();
 }
@@ -626,7 +626,7 @@ bool User::isConnected() const
 
 bool User::isDesktopNotificationsAllowed() const
 {
-    return _account.data()->notificationStatus() == "online";
+    return _account.data()->isDesktopNotificationsAllowed();
 }
 
 void User::removeAccount() const
@@ -736,7 +736,7 @@ void UserModel::addUser(AccountStatePtr &user, const bool &isCurrent)
            emit dataChanged(index(row, 0), index(row, 0), {UserModel::AvatarRole});
         });
 
-        connect(u, &User::userStatusChanged, this, [this, row] {
+        connect(u, &User::statusChanged, this, [this, row] {
             emit dataChanged(index(row, 0), index(row, 0), {UserModel::StatusIconRole, 
                                                             UserModel::StatusMessageRole});
         });
index a737633bd6dcb50e5194c250ec0881d3c12cf67c..bc38b9ea1f891da49f1aabfb4210310555042f29 100644 (file)
@@ -19,8 +19,8 @@ class User : public QObject
     Q_OBJECT
     Q_PROPERTY(QString name READ name NOTIFY nameChanged)
     Q_PROPERTY(QString server READ server CONSTANT)
-    Q_PROPERTY(QUrl statusIcon READ statusIcon NOTIFY userStatusChanged)
-    Q_PROPERTY(QString statusMessage READ statusMessage NOTIFY userStatusChanged)
+    Q_PROPERTY(QUrl statusIcon READ statusIcon NOTIFY statusChanged)
+    Q_PROPERTY(QString statusMessage READ statusMessage NOTIFY statusChanged)
     Q_PROPERTY(bool hasLocalFolder READ hasLocalFolder NOTIFY hasLocalFolderChanged)
     Q_PROPERTY(bool serverHasTalk READ serverHasTalk NOTIFY serverHasTalkChanged)
     Q_PROPERTY(QString avatar READ avatarUrl NOTIFY avatarChanged)
@@ -48,7 +48,7 @@ public:
     void removeAccount() const;
     QString avatarUrl() const;
     bool isDesktopNotificationsAllowed() const;
-    QString status() const;
+    UserStatus::Status status() const;
     QString statusMessage() const;
     QUrl statusIcon() const;
 
@@ -59,7 +59,7 @@ signals:
     void serverHasTalkChanged();
     void avatarChanged();
     void accountStateChanged(int state);
-    void userStatusChanged();
+    void statusChanged();
 
 public slots:
     void slotItemCompleted(const QString &folder, const SyncFileItemPtr &item);
index 7b8c7d54208197c4ad6f8f6e929d5b6750ac211d..5030158e64ddea5ba1b6a674b00cc3c65fb20e8f 100644 (file)
@@ -28,10 +28,16 @@ namespace OCC {
 
 UserStatus::UserStatus(QObject *parent)
     : QObject(parent)
-    , _status("online")
     , _message("")
 {
+}
 
+UserStatus::Status UserStatus::stringToEnum(const QString &status) const 
+{
+    // api should return invisible, dnd,... toLower() it is to make sure 
+    // it matches _preDefinedStatus, otherwise the default is online (0)
+    const auto statusEnum = _preDefinedStatus.value(status.isEmpty()? "online" : status.toLower(), 0);
+    return static_cast<Status>(statusEnum);
 }
 
 void UserStatus::fetchUserStatus(AccountPtr account)
@@ -50,17 +56,22 @@ void UserStatus::slotFetchUserStatusFinished(const QJsonDocument &json)
     const auto retrievedData = json.object().value("ocs").toObject().value("data").toObject();
     const auto emoji = retrievedData.value("icon").toString();
     const auto message = retrievedData.value("message").toString();
-    _status = retrievedData.value("status").toString();
+    auto statusString = retrievedData.value("status").toString(); 
+    _status = stringToEnum(statusString);
+    
+    // to display it to the user like 'Invisible' instead of 'invisible'
+    statusString.replace(0, 1, statusString.at(0).toUpper());  
 
     const auto visibleStatusText = message.isEmpty()
-                                ? _status == "dnd"? tr("Do not disturb") : _status
+                                ? _status == DoNotDisturb? tr("Do not disturb") 
+                                                : tr(qPrintable(statusString))
                                 : message;
 
     _message = QString("%1 %2").arg(emoji, visibleStatusText);
     emit fetchUserStatusFinished();
 }
 
-QString UserStatus::status() const
+UserStatus::Status UserStatus::status() const
 {
     return _status;
 }
@@ -72,20 +83,19 @@ QString UserStatus::message() const
 
 QUrl UserStatus::icon() const
 {
-    // online, away, dnd, invisible, offline
-    if(_status == "online") {
+    switch (_status) {
+    case Online:
         return Theme::instance()->statusOnlineImageSource();
-    } else if (_status == "away") {
+    case Away:
         return Theme::instance()->statusAwayImageSource();
-    } else if (_status == "dnd") {
+    case DoNotDisturb:
         return Theme::instance()->statusDoNotDisturbImageSource();
-    } else if (_status == "invisible") {
-        return Theme::instance()->statusInvisibleImageSource();
-    } else if (_status == "offline") {
+    case Invisible:
+    case Offline:
         return Theme::instance()->statusInvisibleImageSource();
+    default:
+        return Theme::instance()->statusOnlineImageSource();
     }
-
-    return Theme::instance()->statusOnlineImageSource();
 }
 
 } // namespace OCC
index d723584b531594d96f933a58d0faba101543bcd2..263f55cd92cdeeed37c695f11625376fc96e132c 100644 (file)
@@ -17,6 +17,8 @@
 
 #include <QObject>
 #include <QPointer>
+#include <QVariant>
+#include <QMetaEnum>
 #include "accountfwd.h"
 
 namespace OCC {
@@ -25,11 +27,19 @@ class JsonApiJob;
 class UserStatus : public QObject
 {
     Q_OBJECT
-
+    
 public:
     explicit UserStatus(QObject *parent = nullptr);
+    enum Status {
+        Online,
+        DoNotDisturb,
+        Away,
+        Offline,
+        Invisible
+    };
+    Q_ENUM(Status);
     void fetchUserStatus(AccountPtr account);
-    QString status() const;
+    Status status() const;
     QString message() const;
     QUrl icon() const;
 
@@ -40,8 +50,17 @@ signals:
     void fetchUserStatusFinished();
 
 private:
+    Status stringToEnum(const QString &status) const;
+    
+    // it needs to match the Status enum
+    const QHash<QString, int> _preDefinedStatus{{"online", 0},
+                                               {"dnd", 1}, //DoNotDisturb
+                                               {"away", 2},
+                                               {"offline", 3},
+                                               {"invisible", 4}};
+
     QPointer<JsonApiJob> _job; // the currently running job
-    QString _status;
+    Status _status{Status::Online};
     QString _message;
 };
 
index 93b4936b2dd8e38a50fadea83e1974f37bef5eeb..1330ff518a97674cccdbe2bcde648f04f10cf0e3 100644 (file)
@@ -871,9 +871,9 @@ bool JsonApiJob::finished()
     if(reply()->rawHeaderList().contains("ETag"))
         emit etagResponseHeaderReceived(reply()->rawHeader("ETag"), statusCode);
 
-    const auto desktopNotificationStatus = reply()->rawHeader(QByteArray("X-Nextcloud-User-Status"));
-    if(!desktopNotificationStatus.isEmpty()) {
-        emit desktopNotificationStatusReceived(desktopNotificationStatus == "online");
+    const auto desktopNotificationsAllowed = reply()->rawHeader(QByteArray("X-Nextcloud-User-Status"));
+    if(!desktopNotificationsAllowed.isEmpty()) {
+        emit allowDesktopNotificationsChanged(desktopNotificationsAllowed == "online");
     }
 
     QJsonParseError error;
index e67eded8f886350f97df47fc35aa3b491bf19c53..0fb0029250db814eb0c6e26196cafb797b2de5b7 100644 (file)
@@ -422,10 +422,10 @@ signals:
     void etagResponseHeaderReceived(const QByteArray &value, int statusCode);
     
     /**
-     * @brief desktopNotificationStatusReceived - signal to report the if user is online or dnd
+     * @brief desktopNotificationStatusReceived - signal to report if notifications are allowed
      * @param status - set desktop notifications allowed status 
      */
-    void desktopNotificationStatusReceived(const bool status);
+    void allowDesktopNotificationsChanged(const bool isAllowed);
 
 private:
     QUrlQuery _additionalParams;