From: Camila Date: Sat, 3 Oct 2020 15:12:16 +0000 (+0200) Subject: Add UserStatus class to retrieve the user status. X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~12^2~21^2~300^2~3 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=f4d8699db85a0e8768a676a6ec556dd31ce22234;p=nextcloud-desktop.git Add UserStatus class to retrieve the user status. - AccountState controls UserStatus. - Display user status in the system tray menu next to user's avatar. Signed-off-by: Camila --- diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 13cde2ff9..d3e943063 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -98,6 +98,7 @@ set(client_SRCS systray.cpp thumbnailjob.cpp userinfo.cpp + userstatus.cpp accountstate.cpp addcertificatedialog.cpp authenticationdialog.cpp diff --git a/src/gui/accountstate.cpp b/src/gui/accountstate.cpp index 90c05fefe..f78dc5f37 100644 --- a/src/gui/accountstate.cpp +++ b/src/gui/accountstate.cpp @@ -21,6 +21,7 @@ #include "logger.h" #include "configfile.h" #include "ocsnavigationappsjob.h" +#include "userstatus.h" #include #include @@ -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*"); @@ -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; diff --git a/src/gui/accountstate.h b/src/gui/accountstate.h index 4c6bba62d..d31ebc7d8 100644 --- a/src/gui/accountstate.h +++ b/src/gui/accountstate.h @@ -31,6 +31,7 @@ class AccountState; class Account; class AccountApp; class RemoteWipe; +class UserStatus; using AccountStatePtr = QExplicitlySharedDataPointer; using AccountAppList = QList; @@ -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 diff --git a/src/gui/tray/UserLine.qml b/src/gui/tray/UserLine.qml index 654aa079c..069bccf2a 100644 --- a/src/gui/tray/UserLine.qml +++ b/src/gui/tray/UserLine.qml @@ -109,6 +109,14 @@ MenuItem { font.pixelSize: 12 font.bold: true } + Label { + id: userStatus + width: 128 + text: status + elide: Text.ElideRight + color: "black" + font.pixelSize: 10 + } Label { id: accountServer width: 128 diff --git a/src/gui/tray/UserModel.cpp b/src/gui/tray/UserModel.cpp index 8a1233be7..54ac107c6 100644 --- a/src/gui/tray/UserModel.cpp +++ b/src/gui/tray/UserModel.cpp @@ -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 UserModel::roleNames() const QHash roles; roles[NameRole] = "name"; roles[ServerRole] = "server"; + roles[StatusRole] = "status"; roles[AvatarRole] = "avatar"; roles[IsCurrentUserRole] = "isCurrentUser"; roles[IsConnectedRole] = "isConnected"; diff --git a/src/gui/tray/UserModel.h b/src/gui/tray/UserModel.h index 6302d1340..1d439d49b 100644 --- a/src/gui/tray/UserModel.h +++ b/src/gui/tray/UserModel.h @@ -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, diff --git a/src/gui/tray/Window.qml b/src/gui/tray/Window.qml index f46bc6100..2a6f39db3 100644 --- a/src/gui/tray/Window.qml +++ b/src/gui/tray/Window.qml @@ -379,9 +379,9 @@ Window { font.bold: true } Label { - id: currentAccountServer + id: currentUserStatus width: Style.currentAccountLabelWidth - text: UserModel.currentUser.server + text: UserModel.currentUser.status elide: Text.ElideRight color: Style.ncTextColor font.pixelSize: Style.subLinePixelSize diff --git a/src/gui/userstatus.cpp b/src/gui/userstatus.cpp new file mode 100644 index 000000000..4a678ae73 --- /dev/null +++ b/src/gui/userstatus.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) by Camila + * + * 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 + +#include +#include +#include + +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 index 000000000..4fa9eabad --- /dev/null +++ b/src/gui/userstatus.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) by Camila + * + * 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 +#include +#include + +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; + QPointer _job; // the currently running job + QString _currentUserStatus; +}; + + +} // namespace OCC + +#endif //USERSTATUS_H