Add UserStatus class to retrieve the user status.
authorCamila <hello@camila.codes>
Sat, 3 Oct 2020 15:12:16 +0000 (17:12 +0200)
committerCamila <hello@camila.codes>
Wed, 24 Mar 2021 14:39:13 +0000 (15:39 +0100)
- AccountState controls UserStatus.
- Display user status in the system tray menu next to user's avatar.

Signed-off-by: Camila <hello@camila.codes>
src/gui/CMakeLists.txt
src/gui/accountstate.cpp
src/gui/accountstate.h
src/gui/tray/UserLine.qml
src/gui/tray/UserModel.cpp
src/gui/tray/UserModel.h
src/gui/tray/Window.qml
src/gui/userstatus.cpp [new file with mode: 0644]
src/gui/userstatus.h [new file with mode: 0644]

index 13cde2ff9b86f00e77de1c347a1ba563df58135e..d3e943063f26fbae77f14d9572738835a17b43c8 100644 (file)
@@ -98,6 +98,7 @@ set(client_SRCS
     systray.cpp
     thumbnailjob.cpp
     userinfo.cpp
+    userstatus.cpp
     accountstate.cpp
     addcertificatedialog.cpp
     authenticationdialog.cpp
index 90c05fefed675b226975cdaf2f68b698a9e63cb7..f78dc5f3765be692015b870c0216e92055003ed0 100644 (file)
@@ -21,6 +21,7 @@
 #include "logger.h"
 #include "configfile.h"
 #include "ocsnavigationappsjob.h"
+#include "userstatus.h"
 
 #include <QSettings>
 #include <QTimer>
@@ -44,6 +45,7 @@ AccountState::AccountState(AccountPtr account)
     , _waitingForNewCredentials(false)
     , _maintenanceToConnectedDelay(60000 + (qrand() % (4 * 60000))) // 1-5min delay
     , _remoteWipe(new RemoteWipe(_account))
+    , _userStatus(new UserStatus(this, this))
 {
     qRegisterMetaType<AccountState *>("AccountState*");
 
@@ -125,6 +127,11 @@ void AccountState::setState(State state)
     emit stateChanged(_state);
 }
 
+QString AccountState::currentUserStatus() const
+{
+    return _userStatus->currentUserStatus();
+}
+
 QString AccountState::stateString(State state)
 {
     switch (state) {
@@ -422,6 +429,10 @@ void AccountState::fetchNavigationApps(){
     job->getNavigationApps();
 }
 
+void AccountState::fetchCurrentUserStatus() {
+    _userStatus->fetchCurrentUserStatus();
+}
+
 void AccountState::slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode){
     if(statusCode == 200){
         qCDebug(lcAccountState) << "New navigation apps ETag Response Header received " << value;
index 4c6bba62d8e7c3959375a8007b221a3210327eca..d31ebc7d80b90d0a29d99853ba0248b5dfde31e8 100644 (file)
@@ -31,6 +31,7 @@ class AccountState;
 class Account;
 class AccountApp;
 class RemoteWipe;
+class UserStatus;
 
 using AccountStatePtr = QExplicitlySharedDataPointer<AccountState>;
 using AccountAppList = QList<AccountApp *>;
@@ -161,6 +162,10 @@ public:
     ///Asks for user credentials
     void handleInvalidCredentials();
 
+    QString currentUserStatus() const;
+
+    void fetchCurrentUserStatus();
+
 public slots:
     /// Triggers a ping to the server to update state and
     /// connection status and errors.
@@ -174,6 +179,7 @@ signals:
     void stateChanged(State state);
     void isConnectedChanged();
     void hasFetchedNavigationApps();
+    void userStatusChanged();
 
 protected Q_SLOTS:
     void slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList &errors);
@@ -223,6 +229,7 @@ private:
      */
     AccountAppList _apps;
 
+    UserStatus *_userStatus;
 };
 
 class AccountApp : public QObject
index 654aa079c47c7eeed90d3738f38801f0eee5dd15..069bccf2ab254fcdad7348dcc6feab0eb13dcf0a 100644 (file)
@@ -109,6 +109,14 @@ MenuItem {
                             font.pixelSize: 12\r
                             font.bold: true\r
                         }\r
+                        Label {\r
+                            id: userStatus\r
+                            width: 128\r
+                            text: status\r
+                            elide: Text.ElideRight\r
+                            color: "black"\r
+                            font.pixelSize: 10\r
+                        }\r
                         Label {\r
                             id: accountServer\r
                             width: 128\r
index 8a1233be7928cd9bf88736914046518f3c374cc0..54ac107c62e4cf22569f15643667207b1d13068d 100644 (file)
@@ -53,6 +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(_activityModel, &ActivityListModel::sendNotificationRequest, this, &User::slotSendNotificationRequest);
 }
@@ -87,7 +88,7 @@ void User::slotBuildNotificationDisplay(const ActivityList &list)
 
             // Assemble a tray notification for the NEW notification
             ConfigFile cfg;
-            if (cfg.optionalServerNotifications()) {
+            if (cfg.optionalServerNotifications() /*and header is not X-Nextcloud-User-Status*/) {
                 if (AccountManager::instance()->accounts().count() == 1) {
                     emit guiLog(activity._subject, "");
                 } else {
@@ -207,6 +208,7 @@ void User::slotRefresh()
             slotRefreshActivities();
         }
         slotRefreshNotifications();
+        _account.data()->fetchCurrentUserStatus();
         timer.start();
     }
 }
@@ -557,6 +559,11 @@ QString User::server(bool shortened) const
     return serverUrl;
 }
 
+QString User::currentUserStatus() const
+{
+    return _account->currentUserStatus();
+}
+
 QImage User::avatar() const
 {
     return AvatarJob::makeCircularAvatar(_account->account()->avatar());
@@ -703,6 +710,10 @@ 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] {
+            emit dataChanged(index(row, 0), index(row, 0), {UserModel::StatusRole});
+        });
+
         _users << u;
         if (isCurrent) {
             _currentUserId = _users.indexOf(_users.last());
@@ -841,6 +852,8 @@ QVariant UserModel::data(const QModelIndex &index, int role) const
         return _users[index.row()]->name();
     } else if (role == ServerRole) {
         return _users[index.row()]->server();
+    } else if (role == StatusRole) {
+        return _users[index.row()]->currentUserStatus();
     } else if (role == AvatarRole) {
         return _users[index.row()]->avatarUrl();
     } else if (role == IsCurrentUserRole) {
@@ -858,6 +871,7 @@ QHash<int, QByteArray> UserModel::roleNames() const
     QHash<int, QByteArray> roles;
     roles[NameRole] = "name";
     roles[ServerRole] = "server";
+    roles[StatusRole] = "status";
     roles[AvatarRole] = "avatar";
     roles[IsCurrentUserRole] = "isCurrentUser";
     roles[IsConnectedRole] = "isConnected";
index 6302d134072433c4713f38f023c20d7f5ef3b034..1d439d49bca517a508a993d3b5c6eccd6eb9ce71 100644 (file)
@@ -19,6 +19,7 @@ class User : public QObject
     Q_OBJECT
     Q_PROPERTY(QString name READ name NOTIFY nameChanged)
     Q_PROPERTY(QString server READ server CONSTANT)
+    Q_PROPERTY(QString status READ currentUserStatus NOTIFY userStatusChanged)
     Q_PROPERTY(bool hasLocalFolder READ hasLocalFolder NOTIFY hasLocalFolderChanged)
     Q_PROPERTY(bool serverHasTalk READ serverHasTalk NOTIFY serverHasTalkChanged)
     Q_PROPERTY(QString avatar READ avatarUrl NOTIFY avatarChanged)
@@ -35,6 +36,7 @@ public:
     void openLocalFolder();
     QString name() const;
     QString server(bool shortened = true) const;
+    QString currentUserStatus() const;
     bool hasLocalFolder() const;
     bool serverHasTalk() const;
     AccountApp *talkApp() const;
@@ -53,6 +55,7 @@ signals:
     void serverHasTalkChanged();
     void avatarChanged();
     void accountStateChanged(int state);
+    void userStatusChanged();
 
 public slots:
     void slotItemCompleted(const QString &folder, const SyncFileItemPtr &item);
@@ -142,6 +145,7 @@ public:
     enum UserRoles {
         NameRole = Qt::UserRole + 1,
         ServerRole,
+        StatusRole,
         AvatarRole,
         IsCurrentUserRole,
         IsConnectedRole,
index f46bc610013138e133988f100784be1834529f6f..2a6f39db30c950a295177c2b32d8dbd2d835158c 100644 (file)
@@ -379,9 +379,9 @@ Window {
                                 font.bold: true\r
                             }\r
                             Label {\r
-                                id: currentAccountServer\r
+                                id: currentUserStatus\r
                                 width: Style.currentAccountLabelWidth\r
-                                text: UserModel.currentUser.server\r
+                                text: UserModel.currentUser.status\r
                                 elide: Text.ElideRight\r
                                 color: Style.ncTextColor\r
                                 font.pixelSize: Style.subLinePixelSize\r
diff --git a/src/gui/userstatus.cpp b/src/gui/userstatus.cpp
new file mode 100644 (file)
index 0000000..4a678ae
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) by Camila <hello@camila.codes>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "userstatus.h"
+#include "account.h"
+#include "accountstate.h"
+#include "networkjobs.h"
+#include "folderman.h"
+#include "creds/abstractcredentials.h"
+#include <theme.h>
+
+#include <QTimer>
+#include <QJsonDocument>
+#include <QJsonObject>
+
+namespace OCC {
+
+UserStatus::UserStatus(AccountState *accountState, QObject *parent)
+    : QObject(parent)
+    , _accountState(accountState)
+{
+    connect(this, &UserStatus::fetchedCurrentUserStatus, _accountState, &AccountState::userStatusChanged);
+}
+
+void UserStatus::fetchCurrentUserStatus()
+{
+    if (_job) {
+        _job->deleteLater();
+    }
+
+    AccountPtr account = _accountState->account();
+    _job = new JsonApiJob(account, QStringLiteral("/ocs/v2.php/apps/user_status/api/v1/user_status"), this);
+    connect(_job.data(), &JsonApiJob::jsonReceived, this, &UserStatus::slotFetchedCurrentStatus);
+    _job->start();
+}
+
+void UserStatus::slotFetchedCurrentStatus(const QJsonDocument &json)
+{
+    const auto retrievedData = json.object().value("ocs").toObject().value("data").toObject();
+    const auto icon = retrievedData.value("icon").toString();
+    const auto message = retrievedData.value("message").toString();
+    auto status = retrievedData.value("status").toString();
+
+    if(message.isEmpty()) {
+        if(status == "dnd") {
+            status = tr("Do not disturb");
+        }
+    } else {
+        status = message;
+    }
+
+    _currentUserStatus = QString("%1 %2").arg(icon, status);
+    emit fetchedCurrentUserStatus();
+}
+
+QString UserStatus::currentUserStatus() const
+{
+    return _currentUserStatus;
+}
+
+} // namespace OCC
diff --git a/src/gui/userstatus.h b/src/gui/userstatus.h
new file mode 100644 (file)
index 0000000..4fa9eab
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) by Camila <hello@camila.codes>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef USERSTATUS_H
+#define USERSTATUS_H
+
+#include <QObject>
+#include <QPointer>
+#include <QVariant>
+
+namespace OCC {
+class AccountState;
+class JsonApiJob;
+
+class UserStatus : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit UserStatus(AccountState *accountState, QObject *parent = nullptr);
+    void fetchCurrentUserStatus();
+    QString currentUserStatus() const;
+
+private slots:
+    void slotFetchedCurrentStatus(const QJsonDocument &json);
+
+signals:
+    void fetchedCurrentUserStatus();
+
+private:
+    QPointer<AccountState> _accountState;
+    QPointer<JsonApiJob> _job; // the currently running job
+    QString _currentUserStatus;
+};
+
+
+} // namespace OCC
+
+#endif //USERSTATUS_H