mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-27 17:37:36 +03:00
Do not display notifications when user status is do not disturb.
- This information is retrieved from the notifications endpoint. - Add icons for the different pre defined status. - Make functions available to QML to decide which status icon to display. - Display the user status icon on the avatar and move the online/offline connection status to the folder icon. Signed-off-by: Camila <hello@camila.codes>
This commit is contained in:
parent
f4d8699db8
commit
974e2fb718
20 changed files with 287 additions and 82 deletions
|
@ -45,7 +45,8 @@ AccountState::AccountState(AccountPtr account)
|
|||
, _waitingForNewCredentials(false)
|
||||
, _maintenanceToConnectedDelay(60000 + (qrand() % (4 * 60000))) // 1-5min delay
|
||||
, _remoteWipe(new RemoteWipe(_account))
|
||||
, _userStatus(new UserStatus(this, this))
|
||||
, _userStatus(new UserStatus(this))
|
||||
, _notificationStatus("online")
|
||||
{
|
||||
qRegisterMetaType<AccountState *>("AccountState*");
|
||||
|
||||
|
@ -127,9 +128,19 @@ void AccountState::setState(State state)
|
|||
emit stateChanged(_state);
|
||||
}
|
||||
|
||||
QString AccountState::currentUserStatus() const
|
||||
QString AccountState::status() const
|
||||
{
|
||||
return _userStatus->currentUserStatus();
|
||||
return _userStatus->status();
|
||||
}
|
||||
|
||||
QString AccountState::statusMessage() const
|
||||
{
|
||||
return _userStatus->message();
|
||||
}
|
||||
|
||||
QUrl AccountState::statusIcon() const
|
||||
{
|
||||
return _userStatus->icon();
|
||||
}
|
||||
|
||||
QString AccountState::stateString(State state)
|
||||
|
@ -212,6 +223,16 @@ void AccountState::setNavigationAppsEtagResponseHeader(const QByteArray &value)
|
|||
_navigationAppsEtagResponseHeader = value;
|
||||
}
|
||||
|
||||
QString AccountState::notificationStatus() const
|
||||
{
|
||||
return _notificationStatus;
|
||||
}
|
||||
|
||||
void AccountState::setNotificationStatus(const QString &status)
|
||||
{
|
||||
_notificationStatus = status;
|
||||
}
|
||||
|
||||
void AccountState::checkConnectivity()
|
||||
{
|
||||
if (isSignedOut() || _waitingForNewCredentials) {
|
||||
|
@ -429,8 +450,10 @@ void AccountState::fetchNavigationApps(){
|
|||
job->getNavigationApps();
|
||||
}
|
||||
|
||||
void AccountState::fetchCurrentUserStatus() {
|
||||
_userStatus->fetchCurrentUserStatus();
|
||||
void AccountState::fetchUserStatus()
|
||||
{
|
||||
connect(_userStatus, &UserStatus::fetchUserStatusFinished, this, &AccountState::userStatusChanged);
|
||||
_userStatus->fetchUserStatus(_account);
|
||||
}
|
||||
|
||||
void AccountState::slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode){
|
||||
|
|
|
@ -162,9 +162,31 @@ public:
|
|||
///Asks for user credentials
|
||||
void handleInvalidCredentials();
|
||||
|
||||
QString currentUserStatus() const;
|
||||
/** Returns the user status (online, dnd, away, offline, invisible)
|
||||
* https://gist.github.com/georgehrke/55a0412007f13be1551d1f9436a39675
|
||||
*/
|
||||
QString status() const;
|
||||
|
||||
void fetchCurrentUserStatus();
|
||||
/** Returns the user status Message (emoji + text)
|
||||
*/
|
||||
QString statusMessage() const;
|
||||
|
||||
/** Returns the user status icon url
|
||||
*/
|
||||
QUrl statusIcon() const;
|
||||
|
||||
/** Returns the user status retrieved by the notificatons endpoint: dnd or online
|
||||
* https://github.com/nextcloud/desktop/issues/2318#issuecomment-680698429
|
||||
*/
|
||||
QString notificationStatus() const;
|
||||
|
||||
/** Set new user status retrieved by the notificatons endpoint: dnd or online
|
||||
*/
|
||||
void setNotificationStatus(const QString &status);
|
||||
|
||||
/** Fetch the user status (status, icon, message)
|
||||
*/
|
||||
void fetchUserStatus();
|
||||
|
||||
public slots:
|
||||
/// Triggers a ping to the server to update state and
|
||||
|
@ -230,6 +252,7 @@ private:
|
|||
AccountAppList _apps;
|
||||
|
||||
UserStatus *_userStatus;
|
||||
QString _notificationStatus;
|
||||
};
|
||||
|
||||
class AccountApp : public QObject
|
||||
|
|
|
@ -48,6 +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);
|
||||
_notificationJob->setProperty(propertyAccountStateC, QVariant::fromValue<AccountState *>(_accountState));
|
||||
_notificationJob->addRawHeader("If-None-Match", _accountState->notificationsEtagResponseHeader());
|
||||
_notificationJob->start();
|
||||
|
@ -62,6 +64,14 @@ void ServerNotificationHandler::slotEtagResponseHeaderReceived(const QByteArray
|
|||
}
|
||||
}
|
||||
|
||||
void ServerNotificationHandler::slotDesktopNotificationStatusReceived(const bool status)
|
||||
{
|
||||
auto *account = qvariant_cast<AccountState *>(sender()->property(propertyAccountStateC));
|
||||
if (account != nullptr) {
|
||||
account->setDesktopNotificationsStatus(status);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerNotificationHandler::slotIconDownloaded(QByteArray iconData)
|
||||
{
|
||||
iconCache.insert(sender()->property("activityId").toInt(),iconData);
|
||||
|
|
|
@ -26,6 +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);
|
||||
|
||||
private:
|
||||
QPointer<JsonApiJob> _notificationJob;
|
||||
|
|
|
@ -35,7 +35,7 @@ MenuItem {
|
|||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onContainsMouseChanged: {
|
||||
accountStateIndicatorBackground.color = (containsMouse ? "#f6f6f6" : "white")
|
||||
accountStatusIndicatorBackground.color = (containsMouse ? "#f6f6f6" : "white")
|
||||
}
|
||||
onClicked: {
|
||||
if (!isCurrentUser) {
|
||||
|
@ -71,8 +71,8 @@ MenuItem {
|
|||
Layout.preferredHeight: (userLineLayout.height -16)
|
||||
Layout.preferredWidth: (userLineLayout.height -16)
|
||||
Rectangle {
|
||||
id: accountStateIndicatorBackground
|
||||
width: accountStateIndicator.sourceSize.width + 2
|
||||
id: accountStatusIndicatorBackground
|
||||
width: accountStatusIndicator.sourceSize.width + 2
|
||||
height: width
|
||||
anchors.bottom: accountAvatar.bottom
|
||||
anchors.right: accountAvatar.right
|
||||
|
@ -80,18 +80,16 @@ MenuItem {
|
|||
radius: width*0.5
|
||||
}
|
||||
Image {
|
||||
id: accountStateIndicator
|
||||
source: model.isConnected
|
||||
? Style.stateOnlineImageSource
|
||||
: Style.stateOfflineImageSource
|
||||
id: accountStatusIndicator
|
||||
source: model.statusIcon
|
||||
cache: false
|
||||
x: accountStateIndicatorBackground.x + 1
|
||||
y: accountStateIndicatorBackground.y + 1
|
||||
x: accountStatusIndicatorBackground.x + 1
|
||||
y: accountStatusIndicatorBackground.y + 1
|
||||
sourceSize.width: Style.accountAvatarStateIndicatorSize
|
||||
sourceSize.height: Style.accountAvatarStateIndicatorSize
|
||||
|
||||
Accessible.role: Accessible.Indicator
|
||||
Accessible.name: model.isConnected ? qsTr("Account connected") : qsTr("Account not connected")
|
||||
Accessible.name: model.isStatusOnline ? qsTr("Current user status is online") : qsTr("Current user status is do not disturb")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,9 +108,9 @@ MenuItem {
|
|||
font.bold: true
|
||||
}
|
||||
Label {
|
||||
id: userStatus
|
||||
id: userStatusMessage
|
||||
width: 128
|
||||
text: status
|
||||
text: statusMessage
|
||||
elide: Text.ElideRight
|
||||
color: "black"
|
||||
font.pixelSize: 10
|
||||
|
@ -231,13 +229,4 @@ MenuItem {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: UserModel
|
||||
onRefreshCurrentUserGui: {
|
||||
accountStateIndicator.source = model.isConnected
|
||||
? Style.stateOnlineImageSource
|
||||
: Style.stateOfflineImageSource
|
||||
}
|
||||
}
|
||||
} // MenuItem userLine
|
||||
|
|
|
@ -88,7 +88,7 @@ void User::slotBuildNotificationDisplay(const ActivityList &list)
|
|||
|
||||
// Assemble a tray notification for the NEW notification
|
||||
ConfigFile cfg;
|
||||
if (cfg.optionalServerNotifications() /*and header is not X-Nextcloud-User-Status*/) {
|
||||
if (cfg.optionalServerNotifications() && isDesktopNotificationsAllowed()) {
|
||||
if (AccountManager::instance()->accounts().count() == 1) {
|
||||
emit guiLog(activity._subject, "");
|
||||
} else {
|
||||
|
@ -208,7 +208,7 @@ void User::slotRefresh()
|
|||
slotRefreshActivities();
|
||||
}
|
||||
slotRefreshNotifications();
|
||||
_account.data()->fetchCurrentUserStatus();
|
||||
_account.data()->fetchUserStatus();
|
||||
timer.start();
|
||||
}
|
||||
}
|
||||
|
@ -559,9 +559,19 @@ QString User::server(bool shortened) const
|
|||
return serverUrl;
|
||||
}
|
||||
|
||||
QString User::currentUserStatus() const
|
||||
QString User::status() const
|
||||
{
|
||||
return _account->currentUserStatus();
|
||||
return _account->status();
|
||||
}
|
||||
|
||||
QString User::statusMessage() const
|
||||
{
|
||||
return _account->statusMessage();
|
||||
}
|
||||
|
||||
QUrl User::statusIcon() const
|
||||
{
|
||||
return _account->statusIcon();
|
||||
}
|
||||
|
||||
QImage User::avatar() const
|
||||
|
@ -613,6 +623,12 @@ bool User::isConnected() const
|
|||
return (_account->connectionStatus() == AccountState::ConnectionStatus::Connected);
|
||||
}
|
||||
|
||||
|
||||
bool User::isDesktopNotificationsAllowed() const
|
||||
{
|
||||
return _account.data()->notificationStatus() == "online";
|
||||
}
|
||||
|
||||
void User::removeAccount() const
|
||||
{
|
||||
AccountManager::instance()->deleteAccount(_account.data());
|
||||
|
@ -674,6 +690,16 @@ Q_INVOKABLE bool UserModel::isUserConnected(const int &id)
|
|||
return _users[id]->isConnected();
|
||||
}
|
||||
|
||||
Q_INVOKABLE QUrl UserModel::statusIcon(const int &id)
|
||||
{
|
||||
if (id < 0 || id >= _users.size()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return _users[id]->statusIcon();
|
||||
}
|
||||
|
||||
|
||||
QImage UserModel::avatarById(const int &id)
|
||||
{
|
||||
if (id < 0 || id >= _users.size())
|
||||
|
@ -711,7 +737,8 @@ void UserModel::addUser(AccountStatePtr &user, const bool &isCurrent)
|
|||
});
|
||||
|
||||
connect(u, &User::userStatusChanged, this, [this, row] {
|
||||
emit dataChanged(index(row, 0), index(row, 0), {UserModel::StatusRole});
|
||||
emit dataChanged(index(row, 0), index(row, 0), {UserModel::StatusIconRole,
|
||||
UserModel::StatusMessageRole});
|
||||
});
|
||||
|
||||
_users << u;
|
||||
|
@ -852,8 +879,10 @@ 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 == StatusIconRole) {
|
||||
return _users[index.row()]->statusIcon();
|
||||
} else if (role == StatusMessageRole) {
|
||||
return _users[index.row()]->statusMessage();
|
||||
} else if (role == AvatarRole) {
|
||||
return _users[index.row()]->avatarUrl();
|
||||
} else if (role == IsCurrentUserRole) {
|
||||
|
@ -871,7 +900,8 @@ QHash<int, QByteArray> UserModel::roleNames() const
|
|||
QHash<int, QByteArray> roles;
|
||||
roles[NameRole] = "name";
|
||||
roles[ServerRole] = "server";
|
||||
roles[StatusRole] = "status";
|
||||
roles[StatusIconRole] = "statusIcon";
|
||||
roles[StatusMessageRole] = "statusMessage";
|
||||
roles[AvatarRole] = "avatar";
|
||||
roles[IsCurrentUserRole] = "isCurrentUser";
|
||||
roles[IsConnectedRole] = "isConnected";
|
||||
|
|
|
@ -19,7 +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(QString status READ currentUserStatus NOTIFY userStatusChanged)
|
||||
Q_PROPERTY(QUrl statusIcon READ statusIcon NOTIFY userStatusChanged)
|
||||
Q_PROPERTY(QString statusMessage READ statusMessage 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)
|
||||
|
@ -36,7 +37,6 @@ public:
|
|||
void openLocalFolder();
|
||||
QString name() const;
|
||||
QString server(bool shortened = true) const;
|
||||
QString currentUserStatus() const;
|
||||
bool hasLocalFolder() const;
|
||||
bool serverHasTalk() const;
|
||||
AccountApp *talkApp() const;
|
||||
|
@ -47,6 +47,10 @@ public:
|
|||
void logout() const;
|
||||
void removeAccount() const;
|
||||
QString avatarUrl() const;
|
||||
bool isDesktopNotificationsAllowed() const;
|
||||
QString status() const;
|
||||
QString statusMessage() const;
|
||||
QUrl statusIcon() const;
|
||||
|
||||
signals:
|
||||
void guiLog(const QString &, const QString &);
|
||||
|
@ -135,6 +139,7 @@ public:
|
|||
Q_INVOKABLE bool currentUserHasLocalFolder();
|
||||
int currentUserId() const;
|
||||
Q_INVOKABLE bool isUserConnected(const int &id);
|
||||
Q_INVOKABLE QUrl statusIcon(const int &id);
|
||||
Q_INVOKABLE void switchCurrentUser(const int &id);
|
||||
Q_INVOKABLE void login(const int &id);
|
||||
Q_INVOKABLE void logout(const int &id);
|
||||
|
@ -145,7 +150,8 @@ public:
|
|||
enum UserRoles {
|
||||
NameRole = Qt::UserRole + 1,
|
||||
ServerRole,
|
||||
StatusRole,
|
||||
StatusIconRole,
|
||||
StatusMessageRole,
|
||||
AvatarRole,
|
||||
IsCurrentUserRole,
|
||||
IsConnectedRole,
|
||||
|
|
|
@ -35,8 +35,8 @@ Window {
|
|||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
currentAccountStateIndicator.source = ""
|
||||
currentAccountStateIndicator.source = UserModel.isUserConnected(UserModel.currentUserId)
|
||||
folderStateIndicator.source = ""
|
||||
folderStateIndicator.source = UserModel.isUserConnected(UserModel.currentUserId)
|
||||
? Style.stateOnlineImageSource
|
||||
: Style.stateOfflineImageSource
|
||||
|
||||
|
@ -49,8 +49,8 @@ Window {
|
|||
Connections {
|
||||
target: UserModel
|
||||
onRefreshCurrentUserGui: {
|
||||
currentAccountStateIndicator.source = ""
|
||||
currentAccountStateIndicator.source = UserModel.isUserConnected(UserModel.currentUserId)
|
||||
folderStateIndicator.source = ""
|
||||
folderStateIndicator.source = UserModel.isUserConnected(UserModel.currentUserId)
|
||||
? Style.stateOnlineImageSource
|
||||
: Style.stateOfflineImageSource
|
||||
}
|
||||
|
@ -328,7 +328,7 @@ Window {
|
|||
Accessible.name: qsTr("Current user avatar")
|
||||
|
||||
Rectangle {
|
||||
id: currentAccountStateIndicatorBackground
|
||||
id: currentAccountStatusIndicatorBackground
|
||||
width: Style.accountAvatarStateIndicatorSize + 2
|
||||
height: width
|
||||
anchors.bottom: currentAccountAvatar.bottom
|
||||
|
@ -348,18 +348,16 @@ Window {
|
|||
}
|
||||
|
||||
Image {
|
||||
id: currentAccountStateIndicator
|
||||
source: UserModel.isUserConnected(UserModel.currentUserId)
|
||||
? Style.stateOnlineImageSource
|
||||
: Style.stateOfflineImageSource
|
||||
id: currentAccountStatusIndicator
|
||||
source: UserModel.currentUser.statusIcon
|
||||
cache: false
|
||||
x: currentAccountStateIndicatorBackground.x + 1
|
||||
y: currentAccountStateIndicatorBackground.y + 1
|
||||
x: currentAccountStatusIndicatorBackground.x + 1
|
||||
y: currentAccountStatusIndicatorBackground.y + 1
|
||||
sourceSize.width: Style.accountAvatarStateIndicatorSize
|
||||
sourceSize.height: Style.accountAvatarStateIndicatorSize
|
||||
|
||||
Accessible.role: Accessible.Indicator
|
||||
Accessible.name: UserModel.isUserConnected(UserModel.currentUserId()) ? qsTr("Connected") : qsTr("Disconnected")
|
||||
Accessible.name: UserModel.isUserStatusOnline(UserModel.currentUserId()) ? qsTr("Current user status is online") : qsTr("Current user status is do not disturb")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -381,7 +379,7 @@ Window {
|
|||
Label {
|
||||
id: currentUserStatus
|
||||
width: Style.currentAccountLabelWidth
|
||||
text: UserModel.currentUser.status
|
||||
text: UserModel.currentUser.statusMessage
|
||||
elide: Text.ElideRight
|
||||
color: Style.ncTextColor
|
||||
font.pixelSize: Style.subLinePixelSize
|
||||
|
@ -423,6 +421,42 @@ Window {
|
|||
Accessible.onPressAction: openLocalFolderButton.clicked()
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: folderStateIndicatorBackground
|
||||
width: Style.folderStateIndicatorSize
|
||||
height: width
|
||||
anchors.top: openLocalFolderButton.verticalCenter
|
||||
anchors.left: openLocalFolderButton.horizontalCenter
|
||||
color: Style.ncBlue
|
||||
radius: width*0.5
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: folderStateRectangle
|
||||
width: Style.folderStateIndicatorSize
|
||||
height: width
|
||||
anchors.bottom: openLocalFolderButton.bottom
|
||||
anchors.right: openLocalFolderButton.right
|
||||
color: openLocalFolderButton.containsMouse ? "white" : "transparent"
|
||||
opacity: 0.2
|
||||
radius: width*0.5
|
||||
}
|
||||
|
||||
Image {
|
||||
id: folderStateIndicator
|
||||
source: UserModel.isUserConnected(UserModel.currentUserId)
|
||||
? Style.stateOnlineImageSource
|
||||
: Style.stateOfflineImageSource
|
||||
cache: false
|
||||
x: folderStateIndicatorBackground.x
|
||||
y: folderStateIndicatorBackground.y
|
||||
sourceSize.width: Style.folderStateIndicatorSize
|
||||
sourceSize.height: Style.folderStateIndicatorSize
|
||||
|
||||
Accessible.role: Accessible.Indicator
|
||||
Accessible.name: UserModel.isUserConnected(UserModel.currentUserId()) ? qsTr("Connected") : qsTr("Disconnected")
|
||||
}
|
||||
|
||||
HeaderButton {
|
||||
id: trayWindowTalkButton
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "networkjobs.h"
|
||||
#include "folderman.h"
|
||||
#include "creds/abstractcredentials.h"
|
||||
#include <theme.h>
|
||||
#include "theme.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QJsonDocument>
|
||||
|
@ -26,47 +26,66 @@
|
|||
|
||||
namespace OCC {
|
||||
|
||||
UserStatus::UserStatus(AccountState *accountState, QObject *parent)
|
||||
UserStatus::UserStatus(QObject *parent)
|
||||
: QObject(parent)
|
||||
, _accountState(accountState)
|
||||
, _status("online")
|
||||
, _message("")
|
||||
{
|
||||
connect(this, &UserStatus::fetchedCurrentUserStatus, _accountState, &AccountState::userStatusChanged);
|
||||
|
||||
}
|
||||
|
||||
void UserStatus::fetchCurrentUserStatus()
|
||||
void UserStatus::fetchUserStatus(AccountPtr account)
|
||||
{
|
||||
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);
|
||||
connect(_job.data(), &JsonApiJob::jsonReceived, this, &UserStatus::slotFetchUserStatusFinished);
|
||||
_job->start();
|
||||
}
|
||||
|
||||
void UserStatus::slotFetchedCurrentStatus(const QJsonDocument &json)
|
||||
void UserStatus::slotFetchUserStatusFinished(const QJsonDocument &json)
|
||||
{
|
||||
const auto retrievedData = json.object().value("ocs").toObject().value("data").toObject();
|
||||
const auto icon = retrievedData.value("icon").toString();
|
||||
const auto emoji = retrievedData.value("icon").toString();
|
||||
const auto message = retrievedData.value("message").toString();
|
||||
auto status = retrievedData.value("status").toString();
|
||||
_status = retrievedData.value("status").toString();
|
||||
|
||||
if(message.isEmpty()) {
|
||||
if(status == "dnd") {
|
||||
status = tr("Do not disturb");
|
||||
}
|
||||
} else {
|
||||
status = message;
|
||||
}
|
||||
const auto visibleStatusText = message.isEmpty()
|
||||
? _status == "dnd"? tr("Do not disturb") : _status
|
||||
: message;
|
||||
|
||||
_currentUserStatus = QString("%1 %2").arg(icon, status);
|
||||
emit fetchedCurrentUserStatus();
|
||||
_message = QString("%1 %2").arg(emoji, visibleStatusText);
|
||||
emit fetchUserStatusFinished();
|
||||
}
|
||||
|
||||
QString UserStatus::currentUserStatus() const
|
||||
QString UserStatus::status() const
|
||||
{
|
||||
return _currentUserStatus;
|
||||
return _status;
|
||||
}
|
||||
|
||||
QString UserStatus::message() const
|
||||
{
|
||||
return _message;
|
||||
}
|
||||
|
||||
QUrl UserStatus::icon() const
|
||||
{
|
||||
// online, away, dnd, invisible, offline
|
||||
if(_status == "online") {
|
||||
return Theme::instance()->statusOnlineImageSource();
|
||||
} else if (_status == "away") {
|
||||
return Theme::instance()->statusAwayImageSource();
|
||||
} else if (_status == "dnd") {
|
||||
return Theme::instance()->statusDoNotDisturbImageSource();
|
||||
} else if (_status == "invisible") {
|
||||
return Theme::instance()->statusInvisibleImageSource();
|
||||
} else if (_status == "offline") {
|
||||
return Theme::instance()->statusInvisibleImageSource();
|
||||
}
|
||||
|
||||
return Theme::instance()->statusOnlineImageSource();
|
||||
}
|
||||
|
||||
} // namespace OCC
|
||||
|
|
|
@ -17,10 +17,9 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include <QVariant>
|
||||
#include "accountfwd.h"
|
||||
|
||||
namespace OCC {
|
||||
class AccountState;
|
||||
class JsonApiJob;
|
||||
|
||||
class UserStatus : public QObject
|
||||
|
@ -28,20 +27,22 @@ class UserStatus : public QObject
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit UserStatus(AccountState *accountState, QObject *parent = nullptr);
|
||||
void fetchCurrentUserStatus();
|
||||
QString currentUserStatus() const;
|
||||
explicit UserStatus(QObject *parent = nullptr);
|
||||
void fetchUserStatus(AccountPtr account);
|
||||
QString status() const;
|
||||
QString message() const;
|
||||
QUrl icon() const;
|
||||
|
||||
private slots:
|
||||
void slotFetchedCurrentStatus(const QJsonDocument &json);
|
||||
void slotFetchUserStatusFinished(const QJsonDocument &json);
|
||||
|
||||
signals:
|
||||
void fetchedCurrentUserStatus();
|
||||
void fetchUserStatusFinished();
|
||||
|
||||
private:
|
||||
QPointer<AccountState> _accountState;
|
||||
QPointer<JsonApiJob> _job; // the currently running job
|
||||
QString _currentUserStatus;
|
||||
QString _status;
|
||||
QString _message;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -871,6 +871,11 @@ 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");
|
||||
}
|
||||
|
||||
QJsonParseError error;
|
||||
auto json = QJsonDocument::fromJson(jsonStr.toUtf8(), &error);
|
||||
// empty or invalid response and status code is != 304 because jsonStr is expected to be empty
|
||||
|
|
|
@ -420,6 +420,12 @@ signals:
|
|||
* @param statusCode - the OCS status code: 100 (!) for success
|
||||
*/
|
||||
void etagResponseHeaderReceived(const QByteArray &value, int statusCode);
|
||||
|
||||
/**
|
||||
* @brief desktopNotificationStatusReceived - signal to report the if user is online or dnd
|
||||
* @param status - set desktop notifications allowed status
|
||||
*/
|
||||
void desktopNotificationStatusReceived(const bool status);
|
||||
|
||||
private:
|
||||
QUrlQuery _additionalParams;
|
||||
|
|
|
@ -139,6 +139,26 @@ QUrl Theme::stateOfflineImageSource() const
|
|||
return imagePathToUrl(themeImagePath("state-offline", 16));
|
||||
}
|
||||
|
||||
QUrl Theme::statusOnlineImageSource() const
|
||||
{
|
||||
return imagePathToUrl(themeImagePath("user-status-online", 16));
|
||||
}
|
||||
|
||||
QUrl Theme::statusDoNotDisturbImageSource() const
|
||||
{
|
||||
return imagePathToUrl(themeImagePath("user-status-dnd", 16));
|
||||
}
|
||||
|
||||
QUrl Theme::statusAwayImageSource() const
|
||||
{
|
||||
return imagePathToUrl(themeImagePath("user-status-away", 16));
|
||||
}
|
||||
|
||||
QUrl Theme::statusInvisibleImageSource() const
|
||||
{
|
||||
return imagePathToUrl(themeImagePath("user-status-invisible", 16));
|
||||
}
|
||||
|
||||
QString Theme::version() const
|
||||
{
|
||||
return MIRALL_VERSION_STRING;
|
||||
|
|
|
@ -42,6 +42,11 @@ class OWNCLOUDSYNC_EXPORT Theme : public QObject
|
|||
Q_PROPERTY(QString appName READ appName CONSTANT)
|
||||
Q_PROPERTY(QUrl stateOnlineImageSource READ stateOnlineImageSource CONSTANT)
|
||||
Q_PROPERTY(QUrl stateOfflineImageSource READ stateOfflineImageSource CONSTANT)
|
||||
Q_PROPERTY(QUrl stateOnlineImageSource READ stateOnlineImageSource CONSTANT)
|
||||
Q_PROPERTY(QUrl statusOnlineImageSource READ statusOnlineImageSource CONSTANT)
|
||||
Q_PROPERTY(QUrl statusDoNotDisturbImageSource READ statusDoNotDisturbImageSource CONSTANT)
|
||||
Q_PROPERTY(QUrl statusAwayImageSource READ statusAwayImageSource CONSTANT)
|
||||
Q_PROPERTY(QUrl statusInvisibleImageSource READ statusInvisibleImageSource CONSTANT)
|
||||
#ifndef TOKEN_AUTH_ONLY
|
||||
Q_PROPERTY(QIcon folderDisabledIcon READ folderDisabledIcon CONSTANT)
|
||||
Q_PROPERTY(QIcon folderOfflineIcon READ folderOfflineIcon CONSTANT)
|
||||
|
@ -122,6 +127,30 @@ public:
|
|||
* @return QUrl full path to an icon
|
||||
*/
|
||||
QUrl stateOfflineImageSource() const;
|
||||
|
||||
/**
|
||||
* @brief Returns full path to an online user status icon
|
||||
* @return QUrl full path to an icon
|
||||
*/
|
||||
QUrl statusOnlineImageSource() const;
|
||||
|
||||
/**
|
||||
* @brief Returns full path to an do not disturb user status icon
|
||||
* @return QUrl full path to an icon
|
||||
*/
|
||||
QUrl statusDoNotDisturbImageSource() const;
|
||||
|
||||
/**
|
||||
* @brief Returns full path to an away user status icon
|
||||
* @return QUrl full path to an icon
|
||||
*/
|
||||
QUrl statusAwayImageSource() const;
|
||||
|
||||
/**
|
||||
* @brief Returns full path to an invisible user status icon
|
||||
* @return QUrl full path to an icon
|
||||
*/
|
||||
QUrl statusInvisibleImageSource() const;
|
||||
|
||||
/**
|
||||
* @brief configFileName
|
||||
|
|
|
@ -195,5 +195,9 @@
|
|||
<file>theme/share.svg</file>
|
||||
<file>theme/reply.svg</file>
|
||||
<file>theme/magnifying-glass.svg</file>
|
||||
<file>theme/colored/user-status-online.svg</file>
|
||||
<file>theme/colored/user-status-invisible.svg</file>
|
||||
<file>theme/colored/user-status-away.svg</file>
|
||||
<file>theme/colored/user-status-dnd.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -33,6 +33,7 @@ QtObject {
|
|||
|
||||
property int accountAvatarSize: (trayWindowHeaderHeight - 16)
|
||||
property int accountAvatarStateIndicatorSize: 16
|
||||
property int folderStateIndicatorSize: 16
|
||||
property int accountLabelWidth: 128
|
||||
|
||||
property int accountDropDownCaretSize: 20
|
||||
|
|
1
theme/colored/user-status-away.svg
Normal file
1
theme/colored/user-status-away.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg width="24" height="24" enable-background="new 0 0 24 24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><rect width="24" height="24" fill="none"/><path d="m10.615 2.1094c-4.8491 0.68106-8.6152 4.8615-8.6152 9.8906 0 5.5 4.5 10 10 10 5.0292 0 9.2096-3.7661 9.8906-8.6152-1.4654 1.601-3.5625 2.6152-5.8906 2.6152-4.4 0-8-3.6-8-8 0-2.3281 1.0143-4.4252 2.6152-5.8906z" fill="#f4a331"/></svg>
|
After Width: | Height: | Size: 415 B |
1
theme/colored/user-status-dnd.svg
Normal file
1
theme/colored/user-status-dnd.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="m12 2c-5.52 0-10 4.48-10 10s4.48 10 10 10 10-4.48 10-10-4.48-10-10-10z" fill="#ed484c"/><path d="m8 10h8c1.108 0 2 0.892 2 2s-0.892 2-2 2h-8c-1.108 0-2-0.892-2-2s0.892-2 2-2z" fill="#fdffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="paint-order:stroke markers fill"/></svg>
|
After Width: | Height: | Size: 445 B |
1
theme/colored/user-status-invisible.svg
Normal file
1
theme/colored/user-status-invisible.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="m12 2c-5.52 0-10 4.48-10 10s4.48 10 10 10 10-4.48 10-10-4.48-10-10-10zm0 4a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6z" fill="#000"/></svg>
|
After Width: | Height: | Size: 295 B |
1
theme/colored/user-status-online.svg
Normal file
1
theme/colored/user-status-online.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg width="24" height="24" enable-background="new 0 0 24 24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m8 16h8v-8h-8v8zm4-14c-5.52 0-10 4.48-10 10s4.48 10 10 10 10-4.48 10-10-4.48-10-10-10z" fill="#49B382"/></svg>
|
After Width: | Height: | Size: 236 B |
Loading…
Reference in a new issue