From d02a609956160a7cc3a510ab48f5ca2a8db31ea3 Mon Sep 17 00:00:00 2001
From: Armin Felder <armin.felder@osalliance.com>
Date: Tue, 13 Nov 2018 00:27:44 +0100
Subject: [PATCH] own user status now working

---
 CustomModels/usermodel.cpp                    | 18 +++++--
 CustomModels/usermodel.h                      |  4 ++
 ...ketchatchangeuserpresancedefaultstatus.cpp | 41 ----------------
 ...cketchatchangeuserpresencedefaultstatus.h} | 14 ++----
 ddpRequests/rocketchatsubscribeuserdata.cpp   |  9 ++++
 ddpRequests/rocketchatsubscribeuserdata.h     | 12 +++++
 engine.pro                                    | 12 +++--
 repos/entities/rocketchatuser.h               | 10 ++--
 rocketchat.cpp                                |  7 +++
 rocketchat.h                                  |  2 +
 rocketchatserver.cpp                          | 48 ++++++++++++++++---
 rocketchatserver.h                            |  8 +++-
 12 files changed, 115 insertions(+), 70 deletions(-)
 delete mode 100644 ddpRequests/rocketchatchangeuserpresancedefaultstatus.cpp
 rename ddpRequests/{rocketchatchangeuserpresancedefaultstatus.h => rocketchatchangeuserpresencedefaultstatus.h} (88%)
 create mode 100644 ddpRequests/rocketchatsubscribeuserdata.cpp
 create mode 100644 ddpRequests/rocketchatsubscribeuserdata.h

diff --git a/CustomModels/usermodel.cpp b/CustomModels/usermodel.cpp
index 1092392..0a991d3 100644
--- a/CustomModels/usermodel.cpp
+++ b/CustomModels/usermodel.cpp
@@ -86,6 +86,7 @@ bool UserModel::insertUser( const QString &channelId, const QSharedPointer<Rocke
 
     if ( !user.isNull() ) {
         QSharedPointer<RocketChatUser> userToAdd;
+        mMutex.lock();
 
         if ( mAllUsers.contains( user->getUserId() ) ) {
             auto oldUser = mAllUsers[user->getUserId()];
@@ -114,6 +115,7 @@ bool UserModel::insertUser( const QString &channelId, const QSharedPointer<Rocke
         }
 
         userMap.insert( channelId, userToAdd );
+        mMutex.unlock();
         setCurrent( getCurrent() );
     } else {
         return true;
@@ -138,10 +140,11 @@ QString UserModel::getCurrent() const
 void UserModel::setCurrent( const QString &value )
 {
     current = value;
-
+    mMutex.lock();
     userOfCurrentChannel.clear();
     beginResetModel();
     QList<QSharedPointer<RocketChatUser>> userList = userMap.values( value );
+    mMutex.unlock();
 
     for ( auto current : userList ) {
         userOfCurrentChannel.insert( current->getUserId(), current );
@@ -157,15 +160,24 @@ void UserModel::onCurrentChannelChanged( const QString &newText )
 
 QSharedPointer<RocketChatUser> UserModel::getUserById( const QString &pId )
 {
-    return mAllUsers.contains( pId ) ? mAllUsers[pId] : nullptr;
+    QSharedPointer<RocketChatUser> user;
+    mMutex.lock();
+
+    if ( mAllUsers.contains( pId ) ) {
+        user = mAllUsers[pId];
+    }
+
+    mMutex.unlock();
+    return user;
 }
 
 void UserModel::addUser( QSharedPointer<RocketChatUser> pUser )
 {
     if ( !pUser.isNull() ) {
+        mMutex.lock();
         mAllUsers.insert( pUser->getUserId(), pUser );
+        mMutex.unlock();
         connect( pUser.data(), &RocketChatUser::statusChanged, this, &UserModel::refreshUserList );
-        
     }
 }
 
diff --git a/CustomModels/usermodel.h b/CustomModels/usermodel.h
index 79f489f..8bf6725 100644
--- a/CustomModels/usermodel.h
+++ b/CustomModels/usermodel.h
@@ -29,6 +29,7 @@
 #include <QDebug>
 #include <QMap>
 #include <QList>
+#include <QMutex>
 
 #include "repos/entities/rocketchatuser.h"
 
@@ -67,6 +68,9 @@ class UserModel: public QAbstractListModel
         QMap<QString, QSharedPointer<RocketChatUser>> userOfCurrentChannel;
         QMap<QString, QSharedPointer<RocketChatUser>> mAllUsers;
         QString current;
+    private:
+        QMutex mMutex;
+
     signals:
         void currentChannelChanged( const QString &newText );
         void countChanged();
diff --git a/ddpRequests/rocketchatchangeuserpresancedefaultstatus.cpp b/ddpRequests/rocketchatchangeuserpresancedefaultstatus.cpp
deleted file mode 100644
index 3757a57..0000000
--- a/ddpRequests/rocketchatchangeuserpresancedefaultstatus.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/********************************************************************************************
- *                                                                                          *
- * Copyright (C) 2017 Armin Felder, Dennis Beier                                            *
- * This file is part of RocketChatMobileEngine <https://git.fairkom.net/chat/fairchat>.     *
- *                                                                                          *
- * RocketChatMobileEngine 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 3 of the License, or                        *
- * (at your option) any later version.                                                      *
- *                                                                                          *
- * RocketChatMobileEngine 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.                                             *
- *                                                                                          *
- * You should have received a copy of the GNU General Public License                        *
- * along with RocketChatMobileEngine. If not, see <http://www.gnu.org/licenses/>.           *
- *                                                                                          *
- ********************************************************************************************/
-
-
-#include "rocketchatchangeuserpresancedefaultstatus.h"
-
-RocketChatChangeUserPresanceDefaultStatus::RocketChatChangeUserPresanceDefaultStatus( const status &pStatus )
-{
-    QJsonArray params;
-
-    QString statusText;
-
-    if ( pStatus == status::AWAY ) {
-        statusText = QStringLiteral( "away" );
-    } else if ( pStatus == status::ONLINE ) {
-        statusText = QStringLiteral( "online" );
-    } else if ( pStatus == status::OFFLINE ) {
-        statusText = QStringLiteral( "offline" );
-    }
-
-    params.append( statusText );
-
-    buildRequest( QStringLiteral( "UserPresence:setDefaultStatus" ), params );
-}
diff --git a/ddpRequests/rocketchatchangeuserpresancedefaultstatus.h b/ddpRequests/rocketchatchangeuserpresencedefaultstatus.h
similarity index 88%
rename from ddpRequests/rocketchatchangeuserpresancedefaultstatus.h
rename to ddpRequests/rocketchatchangeuserpresencedefaultstatus.h
index a6d894b..cef6bb3 100644
--- a/ddpRequests/rocketchatchangeuserpresancedefaultstatus.h
+++ b/ddpRequests/rocketchatchangeuserpresencedefaultstatus.h
@@ -23,18 +23,14 @@
 #define ROCKETCHATCHANGEUSERPRESANCEDEFAULTSTATUS_H
 
 #include "ddpmethodrequest.h"
+#include "repos/entities/rocketchatuser.h"
 
-class RocketChatChangeUserPresanceDefaultStatus:  public DDPMethodRequest
+
+class RocketChatChangeUserPresenceDefaultStatus:  public DDPMethodRequest
 {
     public:
-        enum class status {
-            ONLINE = 1,
-            AWAY = 2,
-            BUSY = 3,
-            OFFLINE = 4
-        };
-
-        RocketChatChangeUserPresanceDefaultStatus( const status &pStatus );
+
+        RocketChatChangeUserPresenceDefaultStatus( const RocketChatUser::status &pStatus );
 
 };
 
diff --git a/ddpRequests/rocketchatsubscribeuserdata.cpp b/ddpRequests/rocketchatsubscribeuserdata.cpp
new file mode 100644
index 0000000..043dc38
--- /dev/null
+++ b/ddpRequests/rocketchatsubscribeuserdata.cpp
@@ -0,0 +1,9 @@
+#include "rocketchatsubscribeuserdata.h"
+
+#include <QJsonArray>
+
+RocketChatSubscribeUserData::RocketChatSubscribeUserData()
+{
+    QJsonArray params = {QJsonValue::Null};
+    buildRequest( QStringLiteral( "userData" ), params );
+}
diff --git a/ddpRequests/rocketchatsubscribeuserdata.h b/ddpRequests/rocketchatsubscribeuserdata.h
new file mode 100644
index 0000000..100fcc1
--- /dev/null
+++ b/ddpRequests/rocketchatsubscribeuserdata.h
@@ -0,0 +1,12 @@
+#ifndef ROCKETCHATSUBSCRIBEUSERDATA_H
+#define ROCKETCHATSUBSCRIBEUSERDATA_H
+
+#include "ddpsubscriptionrequest.h"
+
+class RocketChatSubscribeUserData: public DDPSubscriptionRequest
+{
+    public:
+        RocketChatSubscribeUserData();
+};
+
+#endif // ROCKETCHATSUBSCRIBEUSERDATA_H
diff --git a/engine.pro b/engine.pro
index 064de0f..2e07cbb 100644
--- a/engine.pro
+++ b/engine.pro
@@ -77,7 +77,7 @@ SOURCES +=  api/meteorddp.cpp \
     container/sortedvector.cpp \
     container/observablelist.cpp \
     container/modelobserver.cpp \
-    ddpRequests/rocketchatchangeuserpresancedefaultstatus.cpp \
+    ddpRequests/rocketchatchangeuserpresencedefaultstatus.cpp \
     CustomModels/messagemodel.cpp \
     CustomModels/loginmethodsmodel.cpp \
     CustomModels/models.cpp \
@@ -100,7 +100,9 @@ SOURCES +=  api/meteorddp.cpp \
     ddpRequests/rocketchatgetroomidbynameorid.cpp \
     ddpRequests/rocketchatspotlightrequest.cpp \
     repos/entities/rocketchatreplymessage.cpp \
-    ddpRequests/rocketchatcreatepublicgrouprequest.cpp
+    ddpRequests/rocketchatcreatepublicgrouprequest.cpp \
+    ddpRequests/rocketchatchangeuserpresencestatus.cpp \
+    ddpRequests/rocketchatsubscribeuserdata.cpp
 
 
 HEADERS += \
@@ -179,7 +181,6 @@ HEADERS += \
     container/sortedvector.h \
     container/observablelist.h \
     container/modelobserver.h \
-    ddpRequests/rocketchatchangeuserpresancedefaultstatus.h \
     config.h \
     CustomModels/messagemodel.h \
     CustomModels/loginmethodsmodel.h \
@@ -204,7 +205,10 @@ HEADERS += \
     ddpRequests/rocketchatspotlightrequest.h \
     api/messagelistener.h \
     repos/entities/rocketchatreplymessage.h \
-    ddpRequests/rocketchatcreatepublicgrouprequest.h
+    ddpRequests/rocketchatcreatepublicgrouprequest.h \
+    ddpRequests/rocketchatchangeuserpresencestatus.h \
+    ddpRequests/rocketchatchangeuserpresencedefaultstatus.h \
+    ddpRequests/rocketchatsubscribeuserdata.h
 
 linux{
 
diff --git a/repos/entities/rocketchatuser.h b/repos/entities/rocketchatuser.h
index 61412d5..6f6c04b 100755
--- a/repos/entities/rocketchatuser.h
+++ b/repos/entities/rocketchatuser.h
@@ -31,11 +31,11 @@ class RocketChatUser : public QObject
 
     public:
 
-        enum class status {
-            ONLINE,
-            AWAY,
-            OFFLINE,
-            BUSY
+        enum class status : int {
+            ONLINE = 0,
+            AWAY = 1,
+            OFFLINE = 2,
+            BUSY = 3
         };
         explicit RocketChatUser( const QString &pId )                                            ;
 
diff --git a/rocketchat.cpp b/rocketchat.cpp
index c07f38b..6c8ca65 100755
--- a/rocketchat.cpp
+++ b/rocketchat.cpp
@@ -264,6 +264,11 @@ void RocketChat::searchRoomByType( const QString &pTerm, const QString &pType )
     QMetaObject::invokeMethod( mServerMap.first(), "searchRoom", Q_ARG( QString, pTerm ), Q_ARG( QString, pType ) );
 }
 
+void RocketChat::setUserDefaultStatus( int pStatus )
+{
+    QMetaObject::invokeMethod( mServerMap.first(), "setUserPresenceDefaultStatus", Q_ARG( int, pStatus ) );
+}
+
 bool RocketChat::newServerByDomain( const QString &domain, bool pUnsecure = false )
 {
     newServerMutex.lock();
@@ -760,6 +765,8 @@ void RocketChat::serverReadySlot()
     connect( pServer, &RocketChatServerData::loggingIn, this, &RocketChat::loggingIn, Qt::UniqueConnection );
     connect( pServer, &RocketChatServerData::historyReady, this, &RocketChat::historyReady, Qt::UniqueConnection );
 
+    connect( pServer, &RocketChatServerData::userStatusChanged, this, &RocketChat::userStatusChanged, Qt::UniqueConnection );
+
     QMetaObject::invokeMethod( pServer, "init" );
 }
 
diff --git a/rocketchat.h b/rocketchat.h
index a2bcc05..802d3a7 100755
--- a/rocketchat.h
+++ b/rocketchat.h
@@ -147,6 +147,7 @@ class RocketChat : public QObject
 
         Q_INVOKABLE void searchRoomByType( const QString &pTerm, const QString &pType );
 
+        Q_INVOKABLE void setUserDefaultStatus( int pStatus );
 
         void registerServer( RocketChatServerData *pServer );
 
@@ -262,6 +263,7 @@ class RocketChat : public QObject
         void pushMessageReceived( QString pServer, QString pRid, QString pName, QString pType );
         void loggingIn();
         void historyReady();
+        void userStatusChanged( int status );
 
 
         // iOS helper
diff --git a/rocketchatserver.cpp b/rocketchatserver.cpp
index cab9219..01face4 100755
--- a/rocketchatserver.cpp
+++ b/rocketchatserver.cpp
@@ -305,12 +305,21 @@ void RocketChatServerData::requestIsLoggedIn()
     }
 }
 
+void RocketChatServerData::setUserPresenceDefaultStatus( int pStatus )
+{
+    if ( pStatus >= 0 && pStatus < 5 && isWebsocketValid() && diffToLastDDPPing() < 29 ) {
+
+        QSharedPointer<DDPMethodRequest> request( new RocketChatChangeUserPresenceDefaultStatus( static_cast<RocketChatUser::status>( pStatus ) ) );
+        sendDdprequest( request, true );
+    }
+}
+
 void RocketChatServerData::setUserPresenceStatus( int pStatus )
 {
-    if ( pStatus > 0 && pStatus < 5 && isWebsocketValid() && diffToLastDDPPing() < 29 ) {
+    if ( pStatus >= 0 && pStatus < 5 && isWebsocketValid() && diffToLastDDPPing() < 29 ) {
 
-        QSharedPointer<DDPMethodRequest> request( new RocketChatChangeUserPresanceDefaultStatus( static_cast<RocketChatChangeUserPresanceDefaultStatus::status>( pStatus ) ) );
-        sendDdprequest( request );
+        QSharedPointer<DDPMethodRequest> request( new RocketChatChangeUserPresenceStatus( static_cast<RocketChatUser::status>( pStatus ) ) );
+        sendDdprequest( request, true );
     }
 }
 
@@ -322,7 +331,7 @@ void RocketChatServerData::onStateChanged( const Qt::ApplicationState &pState )
         qDebug() << "call resume";
         resume();
     } else {
-        setUserPresenceStatus( 1 );
+        setUserPresenceStatus( static_cast<int>( RocketChatUser::status::ONLINE ) );
     }
 }
 
@@ -432,7 +441,20 @@ QString RocketChatServerData::getUserId() const
 
 void RocketChatServerData::setUserId( const QString &userId )
 {
+    auto users = Models::getUsersModel();
+    auto user = users->getUserById( userId );
+
+    if ( user.isNull() ) {
+        user = QSharedPointer<RocketChatUser>( new RocketChatUser( userId ) );
+        QMetaObject::invokeMethod( userModel, "addUser", Q_ARG( User, user ) );
+    }
+
+    mOwnUser = user;
     mUserId = userId;
+
+    connect( user.data(), &RocketChatUser::statusChanged, this, [ = ]() {
+        emit userStatusChanged( static_cast<int>( user->getStatus() ) );
+    } );
 }
 
 void RocketChatServerData::checkForMissedMessages()
@@ -626,6 +648,7 @@ void RocketChatServerData::loginWithHash( const QString &pUsername, const QStrin
                 double expireDouble = expireObject[QStringLiteral( "$date" )].toDouble();
                 self->mTokenExpire = static_cast<uint>( expireDouble / 1000 );
                 QString userId = result[QStringLiteral( "id" )].toString();
+                self->setUserId( userId );
                 self->mStorage->transaction();
                 self->mStorage->setUserData( pUsername, pPswHash );
                 self->mStorage->setToken( self->mResumeToken, self->mTokenExpire );
@@ -688,6 +711,7 @@ void RocketChatServerData::loginWithToken( const QString &pUsername, const QStri
                     self->mTokenExpire = static_cast<uint>( expireDouble / 1000 );
 
                     QString userId = result[QStringLiteral( "id" )].toString();
+                    self->setUserId( userId );
                     self->mStorage->setToken( self->mResumeToken, self->mTokenExpire );
                     self->mStorage->setUserId( userId );
                     self->mRestApi->setToken( self->mResumeToken );
@@ -767,6 +791,7 @@ void RocketChatServerData::loginWtihSamlToken( const QString &pToken )
                     mTokenExpire = static_cast<uint>( expireDouble / 1000 );
                     
                     QString userId = result[QStringLiteral( "id" )].toString();
+                    setUserId( userId );
                     mStorage->setToken( mResumeToken, mTokenExpire );
                     mStorage->setUserId( userId );
                     mRestApi->setToken( mResumeToken );
@@ -839,6 +864,7 @@ void RocketChatServerData::loginWithOpenIDToken( const QString &pToken, const QS
 
                     QString userId = result[QStringLiteral( "id" )].toString();
 
+                    self->setUserId( userId );
                     self->mRestApi->setToken( mResumeToken );
                     self->mRestApi->setUserId( userId );
                     self->mUserId = result[QStringLiteral( "id" )].toString();
@@ -932,7 +958,7 @@ void RocketChatServerData::onDDPAuthenticated()
 {
     //TODO: dirty fix!
     getCustomEmojis();
-    setUserPresenceStatus( 1 );
+    setUserPresenceStatus( static_cast<int>( RocketChatUser::status::ONLINE ) );
     mStorage->setSetting( QStringLiteral( "currentServer" ), mBaseUrl );
     getServerInfo();
 
@@ -1188,7 +1214,10 @@ void RocketChatServerData::onDDPMessageReceived( const QJsonObject &pMessage )
             if ( !user.isNull() ) {
                 if ( msg == QStringLiteral( "added" ) || msg == QStringLiteral( "changed" ) ) {
 
-                    if ( fields.contains( QStringLiteral( "status" ) ) ) {
+                    if ( fields.contains( QStringLiteral( "statusDefault" ) ) && userId == mUserId ) {
+                        QString msgStatus = fields[QStringLiteral( "statusDefault" )].toString();
+                        user->setStatus( msgStatus );
+                    } else if ( fields.contains( QStringLiteral( "status" ) ) ) {
                         QString msgStatus = fields[QStringLiteral( "status" )].toString();
                         user->setStatus( msgStatus );
                     }
@@ -1208,7 +1237,10 @@ void RocketChatServerData::onDDPMessageReceived( const QJsonObject &pMessage )
                 if ( pMessage.contains( "fields" ) ) {
                     QJsonObject fields = pMessage["fields"].toObject();
 
-                    if ( fields.contains( QStringLiteral( "status" ) ) ) {
+                    if ( fields.contains( QStringLiteral( "statusDefault" ) ) && userId == mUserId ) {
+                        QString msgStatus = fields[QStringLiteral( "statusDefault" )].toString();
+                        newUser->setStatus( msgStatus );
+                    } else if ( fields.contains( QStringLiteral( "status" ) ) && userId != mUserId ) {
                         QString msgStatus = fields[QStringLiteral( "status" )].toString();
                         newUser->setStatus( msgStatus );
                     }
@@ -1714,11 +1746,13 @@ void RocketChatServerData::getCustomEmojis()
         QSharedPointer<RocketChatNotifyNoticesRequest> notifyNoticeSubSubscription( new RocketChatNotifyNoticesRequest( this->mUserId ) );
         QSharedPointer<RocketChatSubScriptionChangedRequest> noitfySubscriptionsSubscription( new RocketChatSubScriptionChangedRequest( this->mUserId ) );
         QSharedPointer<RocketChatSubscribeActiveUsers> activeUsersSubscription( new RocketChatSubscribeActiveUsers() );
+        QSharedPointer<RocketChatSubscribeUserData> userData( new RocketChatSubscribeUserData() );
         sendDdprequest( notifySubSubscription, true );
         sendDdprequest( notifyNoticeSubSubscription, true );
         sendDdprequest( noitfySubscriptionsSubscription, true );
         sendDdprequest( activeUsersSubscription, true );
         sendDdprequest( notifyRoomsChanged, true );
+        sendDdprequest( userData, true );
 
         onLoggedIn();
         sendUnsentMessages();
diff --git a/rocketchatserver.h b/rocketchatserver.h
index 46508a2..2398074 100755
--- a/rocketchatserver.h
+++ b/rocketchatserver.h
@@ -57,7 +57,9 @@
 #include "ddpRequests/rocketchatupdatepushtokenrequest.h"
 #include "ddpRequests/ddplogoutrequest.h"
 #include "ddpRequests/rocketchatsubscribeactiveusers.h"
-#include "ddpRequests/rocketchatchangeuserpresancedefaultstatus.h"
+#include "ddpRequests/rocketchatsubscribeuserdata.h"
+#include "ddpRequests/rocketchatchangeuserpresencedefaultstatus.h"
+#include "ddpRequests/rocketchatchangeuserpresencestatus.h"
 #include "ddpRequests/rocketchatupdatejitsitimeout.h"
 #include "ddpRequests/rocketchatsubscribeloginmethods.h"
 #include "ddpRequests/ddpopenidloginrequest.h"
@@ -186,6 +188,8 @@ class RocketChatServerData : public MessageListener
 
         void requestIsLoggedIn();
 
+        void setUserPresenceDefaultStatus( int pStatus );
+
         void setUserPresenceStatus( int pStatus );
 
         void onStateChanged( const Qt::ApplicationState &pState );
@@ -257,6 +261,7 @@ class RocketChatServerData : public MessageListener
         uint mTokenExpire = 0;
         QString mResumeToken;
         bool mUnsecureConnection = false;
+        QSharedPointer<RocketChatUser> mOwnUser;
 
         MeteorDDP *mDdpApi = nullptr;
         RestApi *mRestApi = nullptr;
@@ -346,6 +351,7 @@ class RocketChatServerData : public MessageListener
         void offlineMode( void );
         void loggingIn();
         void historyReady();
+        void userStatusChanged( int status );
 
         // MessageListener interface
     public:
-- 
GitLab