mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-22 21:15:55 +03:00
Merge pull request #3182 from nextcloud/bugfix/user-status
Bugfix/user status
This commit is contained in:
commit
5d2cfd8429
10 changed files with 209 additions and 128 deletions
|
@ -142,6 +142,11 @@ QUrl AccountState::statusIcon() const
|
|||
return _userStatus->icon();
|
||||
}
|
||||
|
||||
QString AccountState::statusEmoji() const
|
||||
{
|
||||
return _userStatus->emoji();
|
||||
}
|
||||
|
||||
QString AccountState::stateString(State state)
|
||||
{
|
||||
switch (state) {
|
||||
|
@ -229,7 +234,12 @@ bool AccountState::isDesktopNotificationsAllowed() const
|
|||
|
||||
void AccountState::setDesktopNotificationsAllowed(bool isAllowed)
|
||||
{
|
||||
if (_isDesktopNotificationsAllowed == isAllowed) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isDesktopNotificationsAllowed = isAllowed;
|
||||
emit desktopNotificationsAllowedChanged();
|
||||
}
|
||||
|
||||
void AccountState::checkConnectivity()
|
||||
|
|
|
@ -167,13 +167,17 @@ public:
|
|||
*/
|
||||
UserStatus::Status status() const;
|
||||
|
||||
/** Returns the user status Message (emoji + text)
|
||||
/** Returns the user status Message (text)
|
||||
*/
|
||||
QString statusMessage() const;
|
||||
|
||||
/** Returns the user status icon url
|
||||
*/
|
||||
QUrl statusIcon() const;
|
||||
|
||||
/** Returns the user status emoji
|
||||
*/
|
||||
QString statusEmoji() const;
|
||||
|
||||
/** Returns the notifications status retrieved by the notificatons endpoint
|
||||
* https://github.com/nextcloud/desktop/issues/2318#issuecomment-680698429
|
||||
|
@ -202,6 +206,7 @@ signals:
|
|||
void isConnectedChanged();
|
||||
void hasFetchedNavigationApps();
|
||||
void statusChanged();
|
||||
void desktopNotificationsAllowedChanged();
|
||||
|
||||
protected Q_SLOTS:
|
||||
void slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList &errors);
|
||||
|
|
|
@ -64,14 +64,16 @@ MenuItem {
|
|||
spacing: 0
|
||||
Image {
|
||||
id: accountAvatar
|
||||
Layout.leftMargin: 4
|
||||
Layout.leftMargin: 7
|
||||
verticalAlignment: Qt.AlignCenter
|
||||
cache: false
|
||||
source: model.avatar != "" ? model.avatar : "image://avatars/fallbackBlack"
|
||||
Layout.preferredHeight: (userLineLayout.height -16)
|
||||
Layout.preferredWidth: (userLineLayout.height -16)
|
||||
Layout.preferredHeight: Style.accountAvatarSize
|
||||
Layout.preferredWidth: Style.accountAvatarSize
|
||||
Rectangle {
|
||||
id: accountStatusIndicatorBackground
|
||||
visible: model.isConnected &&
|
||||
model.serverHasUserStatus
|
||||
width: accountStatusIndicator.sourceSize.width + 2
|
||||
height: width
|
||||
anchors.bottom: accountAvatar.bottom
|
||||
|
@ -81,7 +83,9 @@ MenuItem {
|
|||
}
|
||||
Image {
|
||||
id: accountStatusIndicator
|
||||
source: model.statusIcon
|
||||
visible: model.isConnected &&
|
||||
model.serverHasUserStatus
|
||||
source: model.statusIcon
|
||||
cache: false
|
||||
x: accountStatusIndicatorBackground.x + 1
|
||||
y: accountStatusIndicatorBackground.y + 1
|
||||
|
@ -89,39 +93,63 @@ MenuItem {
|
|||
sourceSize.height: Style.accountAvatarStateIndicatorSize
|
||||
|
||||
Accessible.role: Accessible.Indicator
|
||||
Accessible.name: model.isStatusOnline ? qsTr("Current user status is online") : qsTr("Current user status is do not disturb")
|
||||
Accessible.name: model.desktopNotificationsAllowed ? qsTr("Current user status is online") : qsTr("Current user status is do not disturb")
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: accountLabels
|
||||
spacing: 4
|
||||
spacing: Style.accountLabelsSpacing
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
Layout.leftMargin: 6
|
||||
Layout.leftMargin: Style.accountLabelsLayoutMargin
|
||||
anchors.top: accountAvatar.top
|
||||
anchors.topMargin: Style.userStatusAnchorsMargin
|
||||
anchors.left: accountAvatar.right
|
||||
anchors.leftMargin: Style.accountLabelsAnchorsMargin
|
||||
Label {
|
||||
id: accountUser
|
||||
width: 128
|
||||
text: name
|
||||
elide: Text.ElideRight
|
||||
color: "black"
|
||||
font.pixelSize: 12
|
||||
font.pixelSize: Style.topLinePixelSize
|
||||
font.bold: true
|
||||
}
|
||||
Label {
|
||||
id: userStatusMessage
|
||||
width: 128
|
||||
text: statusMessage
|
||||
elide: Text.ElideRight
|
||||
color: "black"
|
||||
font.pixelSize: 10
|
||||
Row {
|
||||
id: userStatus
|
||||
visible: model.isConnected &&
|
||||
model.serverHasUserStatus
|
||||
anchors.top: accountUser.bottom
|
||||
Label {
|
||||
id: emoji
|
||||
visible: model.statusEmoji !== ""
|
||||
width: Style.userStatusEmojiSize
|
||||
text: statusEmoji
|
||||
}
|
||||
Label {
|
||||
id: message
|
||||
anchors.bottom: emoji.bottom
|
||||
anchors.left: emoji.right
|
||||
anchors.leftMargin: emoji.width + Style.userStatusSpacing
|
||||
visible: model.statusMessage !== ""
|
||||
width: Style.currentAccountLabelWidth
|
||||
text: statusMessage
|
||||
elide: Text.ElideRight
|
||||
color: "black"
|
||||
font.pixelSize: Style.subLinePixelSize
|
||||
}
|
||||
}
|
||||
Label {
|
||||
id: accountServer
|
||||
width: 128
|
||||
anchors.top: userStatus.bottom
|
||||
anchors.topMargin: message.visible
|
||||
? message.height + Style.accountServerAnchorsMargin
|
||||
: Style.userStatusAnchorsMargin
|
||||
width: Style.currentAccountLabelWidth
|
||||
text: server
|
||||
elide: Text.ElideRight
|
||||
color: "black"
|
||||
font.pixelSize: 10
|
||||
font.pixelSize: Style.subLinePixelSize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ User::User(AccountStatePtr &account, const bool &isCurrent, QObject *parent)
|
|||
|
||||
connect(_account->account().data(), &Account::accountChangedAvatar, this, &User::avatarChanged);
|
||||
connect(_account.data(), &AccountState::statusChanged, this, &User::statusChanged);
|
||||
connect(_account.data(), &AccountState::desktopNotificationsAllowedChanged, this, &User::desktopNotificationsAllowedChanged);
|
||||
|
||||
connect(_activityModel, &ActivityListModel::sendNotificationRequest, this, &User::slotSendNotificationRequest);
|
||||
}
|
||||
|
@ -214,7 +215,6 @@ void User::slotRefreshActivities()
|
|||
|
||||
void User::slotRefreshUserStatus()
|
||||
{
|
||||
// TODO: check for _account->account()->capabilities().userStatus()
|
||||
if (_account.data() && _account.data()->isConnected()) {
|
||||
_account.data()->fetchUserStatus();
|
||||
}
|
||||
|
@ -576,6 +576,16 @@ QUrl User::statusIcon() const
|
|||
return _account->statusIcon();
|
||||
}
|
||||
|
||||
QString User::statusEmoji() const
|
||||
{
|
||||
return _account->statusEmoji();
|
||||
}
|
||||
|
||||
bool User::serverHasUserStatus() const
|
||||
{
|
||||
return _account->account()->capabilities().userStatus();
|
||||
}
|
||||
|
||||
QImage User::avatar() const
|
||||
{
|
||||
return AvatarJob::makeCircularAvatar(_account->account()->avatar());
|
||||
|
@ -669,7 +679,6 @@ void UserModel::buildUserList()
|
|||
}
|
||||
if (_init) {
|
||||
_users.first()->setCurrentUser(true);
|
||||
connect(_users.first(), &User::accountStateChanged, this, &UserModel::refreshCurrentUserGui);
|
||||
_init = false;
|
||||
}
|
||||
}
|
||||
|
@ -692,16 +701,6 @@ Q_INVOKABLE bool UserModel::isUserConnected(const int &id)
|
|||
return _users[id]->isConnected();
|
||||
}
|
||||
|
||||
Q_INVOKABLE QUrl UserModel::statusIcon(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())
|
||||
|
@ -740,13 +739,21 @@ void UserModel::addUser(AccountStatePtr &user, const bool &isCurrent)
|
|||
|
||||
connect(u, &User::statusChanged, this, [this, row] {
|
||||
emit dataChanged(index(row, 0), index(row, 0), {UserModel::StatusIconRole,
|
||||
UserModel::StatusEmojiRole,
|
||||
UserModel::StatusMessageRole});
|
||||
});
|
||||
|
||||
connect(u, &User::desktopNotificationsAllowedChanged, this, [this, row] {
|
||||
emit dataChanged(index(row, 0), index(row, 0), { UserModel::DesktopNotificationsAllowedRole });
|
||||
});
|
||||
|
||||
connect(u, &User::accountStateChanged, this, [this, row] {
|
||||
emit dataChanged(index(row, 0), index(row, 0), { UserModel::IsConnectedRole });
|
||||
});
|
||||
|
||||
_users << u;
|
||||
if (isCurrent) {
|
||||
_currentUserId = _users.indexOf(_users.last());
|
||||
connect(u, &User::accountStateChanged, this, &UserModel::refreshCurrentUserGui);
|
||||
}
|
||||
|
||||
endInsertRows();
|
||||
|
@ -799,13 +806,10 @@ Q_INVOKABLE void UserModel::switchCurrentUser(const int &id)
|
|||
{
|
||||
if (_currentUserId < 0 || _currentUserId >= _users.size())
|
||||
return;
|
||||
|
||||
disconnect(_users[_currentUserId], &User::accountStateChanged, this, &UserModel::refreshCurrentUserGui);
|
||||
|
||||
_users[_currentUserId]->setCurrentUser(false);
|
||||
_users[id]->setCurrentUser(true);
|
||||
connect(_users[id], &User::accountStateChanged, this, &UserModel::refreshCurrentUserGui);
|
||||
_currentUserId = id;
|
||||
emit refreshCurrentUserGui();
|
||||
emit newUserSelected();
|
||||
}
|
||||
|
||||
|
@ -815,7 +819,6 @@ Q_INVOKABLE void UserModel::login(const int &id)
|
|||
return;
|
||||
|
||||
_users[id]->login();
|
||||
emit refreshCurrentUserGui();
|
||||
}
|
||||
|
||||
Q_INVOKABLE void UserModel::logout(const int &id)
|
||||
|
@ -824,7 +827,6 @@ Q_INVOKABLE void UserModel::logout(const int &id)
|
|||
return;
|
||||
|
||||
_users[id]->logout();
|
||||
emit refreshCurrentUserGui();
|
||||
}
|
||||
|
||||
Q_INVOKABLE void UserModel::removeAccount(const int &id)
|
||||
|
@ -847,10 +849,6 @@ Q_INVOKABLE void UserModel::removeAccount(const int &id)
|
|||
return;
|
||||
}
|
||||
|
||||
if (_users[id]->isCurrentUser()) {
|
||||
disconnect(_users[id], &User::accountStateChanged, this, &UserModel::refreshCurrentUserGui);
|
||||
}
|
||||
|
||||
if (_users[id]->isCurrentUser() && _users.count() > 1) {
|
||||
id == 0 ? switchCurrentUser(1) : switchCurrentUser(0);
|
||||
}
|
||||
|
@ -861,8 +859,6 @@ Q_INVOKABLE void UserModel::removeAccount(const int &id)
|
|||
beginRemoveRows(QModelIndex(), id, id);
|
||||
_users.removeAt(id);
|
||||
endRemoveRows();
|
||||
|
||||
emit refreshCurrentUserGui();
|
||||
}
|
||||
|
||||
int UserModel::rowCount(const QModelIndex &parent) const
|
||||
|
@ -881,10 +877,16 @@ 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 == ServerHasUserStatusRole) {
|
||||
return _users[index.row()]->serverHasUserStatus();
|
||||
} else if (role == StatusIconRole) {
|
||||
return _users[index.row()]->statusIcon();
|
||||
} else if (role == StatusEmojiRole) {
|
||||
return _users[index.row()]->statusEmoji();
|
||||
} else if (role == StatusMessageRole) {
|
||||
return _users[index.row()]->statusMessage();
|
||||
} else if (role == DesktopNotificationsAllowedRole) {
|
||||
return _users[index.row()]->isDesktopNotificationsAllowed();
|
||||
} else if (role == AvatarRole) {
|
||||
return _users[index.row()]->avatarUrl();
|
||||
} else if (role == IsCurrentUserRole) {
|
||||
|
@ -902,8 +904,11 @@ QHash<int, QByteArray> UserModel::roleNames() const
|
|||
QHash<int, QByteArray> roles;
|
||||
roles[NameRole] = "name";
|
||||
roles[ServerRole] = "server";
|
||||
roles[ServerHasUserStatusRole] = "serverHasUserStatus";
|
||||
roles[StatusIconRole] = "statusIcon";
|
||||
roles[StatusEmojiRole] = "statusEmoji";
|
||||
roles[StatusMessageRole] = "statusMessage";
|
||||
roles[DesktopNotificationsAllowedRole] = "desktopNotificationsAllowed";
|
||||
roles[AvatarRole] = "avatar";
|
||||
roles[IsCurrentUserRole] = "isCurrentUser";
|
||||
roles[IsConnectedRole] = "isConnected";
|
||||
|
@ -919,22 +924,6 @@ ActivityListModel *UserModel::currentActivityModel()
|
|||
return _users[currentUserIndex()]->getActivityModel();
|
||||
}
|
||||
|
||||
bool UserModel::currentUserHasActivities()
|
||||
{
|
||||
if (currentUserIndex() < 0 || currentUserIndex() >= _users.size())
|
||||
return false;
|
||||
|
||||
return _users[currentUserIndex()]->hasActivities();
|
||||
}
|
||||
|
||||
bool UserModel::currentUserHasLocalFolder()
|
||||
{
|
||||
if (currentUserIndex() < 0 || currentUserIndex() >= _users.size())
|
||||
return false;
|
||||
|
||||
return _users[currentUserIndex()]->getFolder() != nullptr;
|
||||
}
|
||||
|
||||
void UserModel::fetchCurrentActivityModel()
|
||||
{
|
||||
if (currentUserId() < 0 || currentUserId() >= _users.size())
|
||||
|
|
|
@ -21,11 +21,15 @@ class User : public QObject
|
|||
Q_OBJECT
|
||||
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
|
||||
Q_PROPERTY(QString server READ server CONSTANT)
|
||||
Q_PROPERTY(bool serverHasUserStatus READ serverHasUserStatus CONSTANT)
|
||||
Q_PROPERTY(QUrl statusIcon READ statusIcon NOTIFY statusChanged)
|
||||
Q_PROPERTY(QString statusEmoji READ statusEmoji NOTIFY statusChanged)
|
||||
Q_PROPERTY(QString statusMessage READ statusMessage NOTIFY statusChanged)
|
||||
Q_PROPERTY(QString desktopNotificationsAllowed READ isDesktopNotificationsAllowed NOTIFY desktopNotificationsAllowedChanged)
|
||||
Q_PROPERTY(bool hasLocalFolder READ hasLocalFolder NOTIFY hasLocalFolderChanged)
|
||||
Q_PROPERTY(bool serverHasTalk READ serverHasTalk NOTIFY serverHasTalkChanged)
|
||||
Q_PROPERTY(QString avatar READ avatarUrl NOTIFY avatarChanged)
|
||||
Q_PROPERTY(bool isConnected READ isConnected NOTIFY accountStateChanged)
|
||||
public:
|
||||
User(AccountStatePtr &account, const bool &isCurrent = false, QObject *parent = nullptr);
|
||||
|
||||
|
@ -41,6 +45,7 @@ public:
|
|||
QString server(bool shortened = true) const;
|
||||
bool hasLocalFolder() const;
|
||||
bool serverHasTalk() const;
|
||||
bool serverHasUserStatus() const;
|
||||
AccountApp *talkApp() const;
|
||||
bool hasActivities() const;
|
||||
AccountAppList appList() const;
|
||||
|
@ -53,6 +58,7 @@ public:
|
|||
UserStatus::Status status() const;
|
||||
QString statusMessage() const;
|
||||
QUrl statusIcon() const;
|
||||
QString statusEmoji() const;
|
||||
void processCompletedSyncItem(const Folder *folder, const SyncFileItemPtr &item);
|
||||
|
||||
signals:
|
||||
|
@ -63,6 +69,7 @@ signals:
|
|||
void avatarChanged();
|
||||
void accountStateChanged(int state);
|
||||
void statusChanged();
|
||||
void desktopNotificationsAllowedChanged();
|
||||
|
||||
public slots:
|
||||
void slotItemCompleted(const QString &folder, const SyncFileItemPtr &item);
|
||||
|
@ -141,11 +148,8 @@ public:
|
|||
Q_INVOKABLE void openCurrentAccountServer();
|
||||
Q_INVOKABLE int numUsers();
|
||||
Q_INVOKABLE QString currentUserServer();
|
||||
Q_INVOKABLE bool currentUserHasActivities();
|
||||
Q_INVOKABLE bool currentUserHasLocalFolder();
|
||||
int currentUserId() const;
|
||||
Q_INVOKABLE bool isUserConnected(const int &id);
|
||||
Q_INVOKABLE QUrl statusIcon(int id);
|
||||
Q_INVOKABLE void switchCurrentUser(const int &id);
|
||||
Q_INVOKABLE void login(const int &id);
|
||||
Q_INVOKABLE void logout(const int &id);
|
||||
|
@ -156,8 +160,11 @@ public:
|
|||
enum UserRoles {
|
||||
NameRole = Qt::UserRole + 1,
|
||||
ServerRole,
|
||||
ServerHasUserStatusRole,
|
||||
StatusIconRole,
|
||||
StatusEmojiRole,
|
||||
StatusMessageRole,
|
||||
DesktopNotificationsAllowedRole,
|
||||
AvatarRole,
|
||||
IsCurrentUserRole,
|
||||
IsConnectedRole,
|
||||
|
@ -168,7 +175,6 @@ public:
|
|||
|
||||
signals:
|
||||
Q_INVOKABLE void addAccount();
|
||||
Q_INVOKABLE void refreshCurrentUserGui();
|
||||
Q_INVOKABLE void newUserSelected();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -35,11 +35,6 @@ Window {
|
|||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
folderStateIndicator.source = ""
|
||||
folderStateIndicator.source = UserModel.isUserConnected(UserModel.currentUserId)
|
||||
? Style.stateOnlineImageSource
|
||||
: Style.stateOfflineImageSource
|
||||
|
||||
// HACK: reload account Instantiator immediately by restting it - could be done better I guess
|
||||
// see also id:accountMenu below
|
||||
userLineInstantiator.active = false;
|
||||
|
@ -48,12 +43,6 @@ Window {
|
|||
|
||||
Connections {
|
||||
target: UserModel
|
||||
onRefreshCurrentUserGui: {
|
||||
folderStateIndicator.source = ""
|
||||
folderStateIndicator.source = UserModel.isUserConnected(UserModel.currentUserId)
|
||||
? Style.stateOnlineImageSource
|
||||
: Style.stateOfflineImageSource
|
||||
}
|
||||
onNewUserSelected: {
|
||||
accountMenu.close();
|
||||
}
|
||||
|
@ -329,6 +318,8 @@ Window {
|
|||
|
||||
Rectangle {
|
||||
id: currentAccountStatusIndicatorBackground
|
||||
visible: UserModel.currentUser.isConnected
|
||||
&& UserModel.currentUser.serverHasUserStatus
|
||||
width: Style.accountAvatarStateIndicatorSize + 2
|
||||
height: width
|
||||
anchors.bottom: currentAccountAvatar.bottom
|
||||
|
@ -338,6 +329,9 @@ Window {
|
|||
}
|
||||
|
||||
Rectangle {
|
||||
id: currentAccountStatusIndicatorMouseHover
|
||||
visible: UserModel.currentUser.isConnected
|
||||
&& UserModel.currentUser.serverHasUserStatus
|
||||
width: Style.accountAvatarStateIndicatorSize + 2
|
||||
height: width
|
||||
anchors.bottom: currentAccountAvatar.bottom
|
||||
|
@ -349,6 +343,8 @@ Window {
|
|||
|
||||
Image {
|
||||
id: currentAccountStatusIndicator
|
||||
visible: UserModel.currentUser.isConnected
|
||||
&& UserModel.currentUser.serverHasUserStatus
|
||||
source: UserModel.currentUser.statusIcon
|
||||
cache: false
|
||||
x: currentAccountStatusIndicatorBackground.x + 1
|
||||
|
@ -357,18 +353,19 @@ Window {
|
|||
sourceSize.height: Style.accountAvatarStateIndicatorSize
|
||||
|
||||
Accessible.role: Accessible.Indicator
|
||||
Accessible.name: UserModel.isUserStatusOnline(UserModel.currentUserId()) ? qsTr("Current user status is online") : qsTr("Current user status is do not disturb")
|
||||
Accessible.name: UserModel.desktopNotificationsAllowed ? qsTr("Current user status is online") : qsTr("Current user status is do not disturb")
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: accountLabels
|
||||
spacing: 4
|
||||
spacing: Style.userStatusSpacing
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
Layout.leftMargin: 6
|
||||
Layout.leftMargin: Style.userStatusSpacing
|
||||
anchors.top: currentAccountAvatar.top
|
||||
anchors.topMargin: Style.userStatusSpacing
|
||||
Label {
|
||||
id: currentAccountUser
|
||||
|
||||
width: Style.currentAccountLabelWidth
|
||||
text: UserModel.currentUser.name
|
||||
elide: Text.ElideRight
|
||||
|
@ -376,13 +373,31 @@ Window {
|
|||
font.pixelSize: Style.topLinePixelSize
|
||||
font.bold: true
|
||||
}
|
||||
Label {
|
||||
Row {
|
||||
id: currentUserStatus
|
||||
width: Style.currentAccountLabelWidth
|
||||
text: UserModel.currentUser.statusMessage
|
||||
elide: Text.ElideRight
|
||||
color: Style.ncTextColor
|
||||
font.pixelSize: Style.subLinePixelSize
|
||||
visible: UserModel.currentUser.isConnected &&
|
||||
UserModel.currentUser.serverHasUserStatus
|
||||
anchors.top: currentAccountUser.bottom
|
||||
Label {
|
||||
id: emoji
|
||||
visible: UserModel.currentUser.statusEmoji !== ""
|
||||
width: Style.userStatusEmojiSize
|
||||
text: UserModel.currentUser.statusEmoji
|
||||
}
|
||||
Label {
|
||||
id: message
|
||||
anchors.bottom: emoji.bottom
|
||||
anchors.left: emoji.right
|
||||
anchors.leftMargin: emoji.width + Style.userStatusSpacing
|
||||
visible: UserModel.currentUser.statusMessage !== ""
|
||||
width: Style.currentAccountLabelWidth
|
||||
text: UserModel.currentUser.statusMessage !== ""
|
||||
? UserModel.currentUser.statusMessage
|
||||
: UserModel.currentUser.server
|
||||
elide: Text.ElideRight
|
||||
color: Style.ncTextColor
|
||||
font.pixelSize: Style.subLinePixelSize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -429,7 +444,8 @@ Window {
|
|||
|
||||
Image {
|
||||
id: folderStateIndicator
|
||||
source: UserModel.isUserConnected(UserModel.currentUserId)
|
||||
visible: UserModel.currentUser.hasLocalFolder
|
||||
source: UserModel.currentUser.isConnected
|
||||
? Style.stateOnlineImageSource
|
||||
: Style.stateOfflineImageSource
|
||||
cache: false
|
||||
|
@ -440,7 +456,7 @@ Window {
|
|||
sourceSize.height: Style.folderStateIndicatorSize
|
||||
|
||||
Accessible.role: Accessible.Indicator
|
||||
Accessible.name: UserModel.isUserConnected(UserModel.currentUserId()) ? qsTr("Connected") : qsTr("Disconnected")
|
||||
Accessible.name: UserModel.currentUser.isConnected ? qsTr("Connected") : qsTr("Disconnected")
|
||||
}
|
||||
|
||||
Accessible.role: Accessible.Button
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "folderman.h"
|
||||
#include "creds/abstractcredentials.h"
|
||||
#include "theme.h"
|
||||
#include "capabilities.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QJsonDocument>
|
||||
|
@ -28,43 +29,52 @@ namespace OCC {
|
|||
|
||||
Q_LOGGING_CATEGORY(lcUserStatus, "nextcloud.gui.userstatus", QtInfoMsg)
|
||||
|
||||
namespace {
|
||||
UserStatus::Status stringToEnum(const QString &status)
|
||||
{
|
||||
// it needs to match the Status enum
|
||||
const QHash<QString, UserStatus::Status> preDefinedStatus{
|
||||
{"online", UserStatus::Status::Online},
|
||||
{"dnd", UserStatus::Status::DoNotDisturb},
|
||||
{"away", UserStatus::Status::Away},
|
||||
{"offline", UserStatus::Status::Offline},
|
||||
{"invisible", UserStatus::Status::Invisible}
|
||||
};
|
||||
|
||||
// api should return invisible, dnd,... toLower() it is to make sure
|
||||
// it matches _preDefinedStatus, otherwise the default is online (0)
|
||||
return preDefinedStatus.value(status.toLower(), UserStatus::Status::Online);
|
||||
}
|
||||
|
||||
QString enumToString(UserStatus::Status status)
|
||||
{
|
||||
switch (status) {
|
||||
case UserStatus::Status::Away:
|
||||
return QObject::tr("Away");
|
||||
case UserStatus::Status::DoNotDisturb:
|
||||
return QObject::tr("Do not disturb");
|
||||
case UserStatus::Status::Invisible:
|
||||
case UserStatus::Status::Offline:
|
||||
return QObject::tr("Offline");
|
||||
case UserStatus::Status::Online:
|
||||
return QObject::tr("Online");
|
||||
}
|
||||
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
UserStatus::UserStatus(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
UserStatus::Status UserStatus::stringToEnum(const QString &status) const
|
||||
{
|
||||
// it needs to match the Status enum
|
||||
const QHash<QString, Status> preDefinedStatus{{"online", Status::Online},
|
||||
{"dnd", Status::DoNotDisturb}, //DoNotDisturb
|
||||
{"away", Status::Away},
|
||||
{"offline", Status::Offline},
|
||||
{"invisible", Status::Invisible}};
|
||||
|
||||
// api should return invisible, dnd,... toLower() it is to make sure
|
||||
// it matches _preDefinedStatus, otherwise the default is online (0)
|
||||
const auto statusKey = status.isEmpty() ? QStringLiteral("online") : status.toLower();
|
||||
return preDefinedStatus.value(statusKey, Status::Online);
|
||||
}
|
||||
|
||||
QString UserStatus::enumToString(Status status) const
|
||||
{
|
||||
switch (status) {
|
||||
case Status::Away:
|
||||
return tr("Away");
|
||||
case Status::DoNotDisturb:
|
||||
return tr("Do not disturb");
|
||||
case Status::Invisible:
|
||||
case Status::Offline:
|
||||
return tr("Offline");
|
||||
default:
|
||||
return tr("Online");
|
||||
}
|
||||
}
|
||||
|
||||
void UserStatus::fetchUserStatus(AccountPtr account)
|
||||
{
|
||||
if (!account->capabilities().userStatus()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_job) {
|
||||
_job->deleteLater();
|
||||
}
|
||||
|
@ -79,7 +89,9 @@ void UserStatus::slotFetchUserStatusFinished(const QJsonDocument &json, int stat
|
|||
const QJsonObject defaultValues {
|
||||
{"icon", ""},
|
||||
{"message", ""},
|
||||
{"status", "online"}
|
||||
{"status", "online"},
|
||||
{"messageIsPredefined", "false"},
|
||||
{"statusIsUserDefined", "false"}
|
||||
};
|
||||
|
||||
if (statusCode != 200) {
|
||||
|
@ -88,13 +100,11 @@ void UserStatus::slotFetchUserStatusFinished(const QJsonDocument &json, int stat
|
|||
}
|
||||
|
||||
const auto retrievedData = json.object().value("ocs").toObject().value("data").toObject(defaultValues);
|
||||
const auto emoji = retrievedData.value("icon").toString();
|
||||
const auto message = retrievedData.value("message").toString();
|
||||
|
||||
_status = stringToEnum(retrievedData.value("status").toString());
|
||||
const auto visibleStatusText = message.isEmpty() ? enumToString(_status) : message;
|
||||
|
||||
_message = QString("%1 %2").arg(emoji, visibleStatusText);
|
||||
_emoji = retrievedData.value("icon").toString().trimmed();
|
||||
_status = stringToEnum(retrievedData.value("status").toString());
|
||||
_message = retrievedData.value("message").toString().trimmed();
|
||||
|
||||
emit fetchUserStatusFinished();
|
||||
}
|
||||
|
||||
|
@ -105,7 +115,12 @@ UserStatus::Status UserStatus::status() const
|
|||
|
||||
QString UserStatus::message() const
|
||||
{
|
||||
return _message.trimmed();
|
||||
return _message;
|
||||
}
|
||||
|
||||
QString UserStatus::emoji() const
|
||||
{
|
||||
return _emoji;
|
||||
}
|
||||
|
||||
QUrl UserStatus::icon() const
|
||||
|
@ -118,9 +133,11 @@ QUrl UserStatus::icon() const
|
|||
case Status::Invisible:
|
||||
case Status::Offline:
|
||||
return Theme::instance()->statusInvisibleImageSource();
|
||||
default:
|
||||
case Status::Online:
|
||||
return Theme::instance()->statusOnlineImageSource();
|
||||
}
|
||||
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
} // namespace OCC
|
||||
|
|
|
@ -39,6 +39,7 @@ public:
|
|||
void fetchUserStatus(AccountPtr account);
|
||||
Status status() const;
|
||||
QString message() const;
|
||||
QString emoji() const;
|
||||
QUrl icon() const;
|
||||
|
||||
private slots:
|
||||
|
@ -48,11 +49,10 @@ signals:
|
|||
void fetchUserStatusFinished();
|
||||
|
||||
private:
|
||||
Status stringToEnum(const QString &status) const;
|
||||
QString enumToString(Status status) const;
|
||||
QPointer<JsonApiJob> _job; // the currently running job
|
||||
Status _status = Status::Online;
|
||||
QString _message;
|
||||
QString _emoji;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -189,7 +189,9 @@ bool Capabilities::chunkingNg() const
|
|||
|
||||
bool Capabilities::userStatus() const
|
||||
{
|
||||
return _capabilities.contains("notifications") && _capabilities["notifications"].toMap().contains("user-status");
|
||||
return _capabilities.contains("notifications") &&
|
||||
_capabilities["notifications"].toMap().contains("ocs-endpoints") &&
|
||||
_capabilities["notifications"].toMap()["ocs-endpoints"].toStringList().contains("user-status");
|
||||
}
|
||||
|
||||
PushNotificationTypes Capabilities::availablePushNotifications() const
|
||||
|
|
|
@ -44,6 +44,14 @@ QtObject {
|
|||
property int headerButtonIconSize: 32
|
||||
|
||||
property int activityLabelBaseWidth: 240
|
||||
|
||||
property int userStatusEmojiSize: 8
|
||||
property int userStatusSpacing: 6
|
||||
property int userStatusAnchorsMargin: 2
|
||||
property int accountServerAnchorsMargin: 10
|
||||
property int accountLabelsSpacing: 4
|
||||
property int accountLabelsAnchorsMargin: 7
|
||||
property int accountLabelsLayoutMargin: 9
|
||||
|
||||
// Visual behaviour
|
||||
property bool hoverEffectsEnabled: true
|
||||
|
|
Loading…
Reference in a new issue