From 0a776b8e94065d6bd3a3e31cf0cea85d2c896452 Mon Sep 17 00:00:00 2001
From: Armin Felder <armin.felder@osalliance.com>
Date: Sun, 11 Nov 2018 22:51:45 +0100
Subject: [PATCH] user status

---
 CustomModels/channelmodel.cpp         | 30 ++++++++++++
 CustomModels/channelmodel.h           |  3 +-
 CustomModels/usermodel.cpp            | 28 ++++++++---
 CustomModels/usermodel.h              |  3 +-
 repos/entities/rocketchatchannel.cpp  | 29 ++++++++++--
 repos/entities/rocketchatchannel.h    | 11 ++++-
 repos/entities/rocketchatuser.cpp     | 30 ++++++++++--
 repos/entities/rocketchatuser.h       |  9 ++--
 rocketchatserver.cpp                  | 67 ++++++++++++++-------------
 services/rocketchatchannelservice.cpp | 60 ++++++++++++++++++++----
 10 files changed, 208 insertions(+), 62 deletions(-)

diff --git a/CustomModels/channelmodel.cpp b/CustomModels/channelmodel.cpp
index 23a7d36..eb22f69 100644
--- a/CustomModels/channelmodel.cpp
+++ b/CustomModels/channelmodel.cpp
@@ -98,6 +98,35 @@ QVariant ChannelModel::data( const QModelIndex &index, int role ) const
         return currentChannel->getUsername();
     }
 
+    if ( role == userStatus ) {
+        int status = 0;
+        auto partner = currentChannel->getChatPartner();
+
+        if ( !partner.isNull() ) {
+            switch ( partner->getStatus() ) {
+                case RocketChatUser::status::ONLINE :
+                    status = 0;
+                    break;
+
+                case RocketChatUser::status::AWAY :
+                    status = 1;
+                    break;
+
+                case RocketChatUser::status::OFFLINE:
+                    status = 2;
+                    break;
+
+                case RocketChatUser::status::BUSY:
+                    status = 3;
+                    break;
+            }
+        }
+
+        return status;
+
+
+    }
+
     return QVariant();
 
 }
@@ -136,6 +165,7 @@ QHash<int, QByteArray> ChannelModel::roleNames() const
     roles[ownerId] = QByteArrayLiteral( "ownerId" );
     roles[ownerName] = QByteArrayLiteral( "ownerName" );
     roles[username] = QByteArrayLiteral( "username" );
+    roles[userStatus] = QByteArrayLiteral( "userStatus" );
 
     return roles;
 }
diff --git a/CustomModels/channelmodel.h b/CustomModels/channelmodel.h
index 681e9d3..cf4b5eb 100644
--- a/CustomModels/channelmodel.h
+++ b/CustomModels/channelmodel.h
@@ -50,7 +50,8 @@ class ChannelModel : public QAbstractListModel
             deleted,
             ownerId,
             ownerName,
-            username
+            username,
+            userStatus
         };
     public:
         ChannelModel();
diff --git a/CustomModels/usermodel.cpp b/CustomModels/usermodel.cpp
index eb969f7..198c1de 100644
--- a/CustomModels/usermodel.cpp
+++ b/CustomModels/usermodel.cpp
@@ -67,6 +67,11 @@ QVariant UserModel::data( const QModelIndex &index, int role ) const
 
             case RocketChatUser::status::OFFLINE:
                 status = 2;
+                break;
+
+            case RocketChatUser::status::BUSY:
+                status = 3;
+                break;
         }
 
         return status;
@@ -82,8 +87,8 @@ bool UserModel::insertUser( const QString &channelId, const QSharedPointer<Rocke
     if ( !user.isNull() ) {
         QSharedPointer<RocketChatUser> userToAdd;
 
-        if ( mAllUsers.contains( user->getUserName() ) ) {
-            auto oldUser = mAllUsers[user->getUserName()];
+        if ( mAllUsers.contains( user->getUserId() ) ) {
+            auto oldUser = mAllUsers[user->getUserId()];
 
             if ( !user->getSurname().isEmpty() ) {
                 oldUser->setSurname( user->getSurname() );
@@ -104,7 +109,8 @@ bool UserModel::insertUser( const QString &channelId, const QSharedPointer<Rocke
             userToAdd = oldUser;
         } else {
             userToAdd = user;
-            mAllUsers.insert( userToAdd->getUserName(), userToAdd );
+            mAllUsers.insert( userToAdd->getUserId(), userToAdd );
+            connect( userToAdd.data(), &RocketChatUser::statusChanged, this, &UserModel::refreshUserList );
         }
 
         userMap.insert( channelId, userToAdd );
@@ -118,6 +124,12 @@ bool UserModel::insertUser( const QString &channelId, const QSharedPointer<Rocke
     return true;
 }
 
+void UserModel::refreshUserList()
+{
+    beginResetModel();
+    endResetModel();
+}
+
 QString UserModel::getCurrent() const
 {
     return current;
@@ -132,7 +144,7 @@ void UserModel::setCurrent( const QString &value )
     QList<QSharedPointer<RocketChatUser>> userList = userMap.values( value );
 
     for ( auto current : userList ) {
-        userOfCurrentChannel.insert( current->getUserName(), current );
+        userOfCurrentChannel.insert( current->getUserId(), current );
     }
 
     endResetModel();
@@ -143,15 +155,17 @@ void UserModel::onCurrentChannelChanged( const QString &newText )
     current = newText;
 }
 
-QSharedPointer<RocketChatUser> UserModel::getUserByUsername( const QString &pUserName )
+QSharedPointer<RocketChatUser> UserModel::getUserById( const QString &pId )
 {
-    return mAllUsers.contains( pUserName ) ? mAllUsers[pUserName] : nullptr;
+    return mAllUsers.contains( pId ) ? mAllUsers[pId] : nullptr;
 }
 
 void UserModel::addUser( QSharedPointer<RocketChatUser> pUser )
 {
     if ( !pUser.isNull() ) {
-        mAllUsers.insert( pUser->getUserName(), pUser );
+        mAllUsers.insert( pUser->getUserId(), pUser );
+        connect( pUser.data(), &RocketChatUser::statusChanged, this, &UserModel::refreshUserList );
+        
     }
 }
 
diff --git a/CustomModels/usermodel.h b/CustomModels/usermodel.h
index 4aec7ee..233bed6 100644
--- a/CustomModels/usermodel.h
+++ b/CustomModels/usermodel.h
@@ -46,6 +46,7 @@ class UserModel: public QAbstractListModel
         };
     public slots:
         bool insertUser( const QString &, const QSharedPointer<RocketChatUser> & );
+        void refreshUserList();
 
     public:
         UserModel( QObject *parent = nullptr );
@@ -55,7 +56,7 @@ class UserModel: public QAbstractListModel
         void setCurrent( const QString &value );
         void onCurrentChannelChanged( const QString &newText );
 
-        QSharedPointer<RocketChatUser> getUserByUsername( const QString &pUserName );
+        QSharedPointer<RocketChatUser> getUserById( const QString &pId );
 
         void addUser( QSharedPointer<RocketChatUser> pUser );
 
diff --git a/repos/entities/rocketchatchannel.cpp b/repos/entities/rocketchatchannel.cpp
index f0fd26f..876b022 100755
--- a/repos/entities/rocketchatchannel.cpp
+++ b/repos/entities/rocketchatchannel.cpp
@@ -90,10 +90,10 @@ void RocketChatChannel::setName( const QString &value )
 
 bool RocketChatChannel::addUser( QSharedPointer<RocketChatUser> user )
 {
-    QString username = user->getUserName();
+    QString userId = user->getUserId();
 
-    if ( mUsers.empty() || !mUsers.contains( username ) ) {
-        mUsers[username] = user;
+    if ( mUsers.empty() || !mUsers.contains( userId ) ) {
+        mUsers[userId] = user;
         return true;
     }
 
@@ -277,6 +277,29 @@ void RocketChatChannel::setUsername( const QString &username )
 {
     mUsername = username;
 }
+
+QSharedPointer<RocketChatUser> RocketChatChannel::getChatPartner() const
+{
+    return mChatPartner;
+}
+
+void RocketChatChannel::setChatPartner( const QSharedPointer<RocketChatUser> &chatPartner )
+{
+    mChatPartner = chatPartner;
+    connect( chatPartner.data(), &RocketChatUser::statusChanged, this, [ = ]() {
+        emit dataChanged( mRoomId, "userStatus" );
+    } );
+}
+
+QString RocketChatChannel::getChatPartnerId() const
+{
+    return mChatPartnerId;
+}
+
+void RocketChatChannel::setChatPartnerId( const QString &chatPartnerId )
+{
+    mChatPartnerId = chatPartnerId;
+}
 bool RocketChatChannel::getBlocked() const
 {
     return mBlocked;
diff --git a/repos/entities/rocketchatchannel.h b/repos/entities/rocketchatchannel.h
index e006388..e91ce98 100755
--- a/repos/entities/rocketchatchannel.h
+++ b/repos/entities/rocketchatchannel.h
@@ -118,7 +118,13 @@ class RocketChatChannel : public QObject
         QString getUsername() const;
         void setUsername( const QString &username );
 
-    protected:
+        QSharedPointer<RocketChatUser> getChatPartner() const;
+        void setChatPartner( const QSharedPointer<RocketChatUser> &chatPartner );
+
+        QString getChatPartnerId() const;
+        void setChatPartnerId( const QString &chatPartnerId );
+
+    private:
         QString mOwnerName;
         QString mOwnerId;
         bool mDeleted;
@@ -129,8 +135,10 @@ class RocketChatChannel : public QObject
         QString mRoomId;
         QString mName;
         QString mUsername;
+        QString mChatPartnerId;
         MessageRepository mMessages;
         QMap<QString, QSharedPointer<RocketChatUser>> mUsers;
+        QSharedPointer<RocketChatUser> mChatPartner;
         bool mJoined = false;
         QString mType;
         unsigned int mUnreadMessages = 0;
@@ -141,6 +149,7 @@ class RocketChatChannel : public QObject
         void unreadMessagesChanged( QString id, int number );
         void channelDeleted( const QString &pId, bool deleted );
         void dataChanged( QString id, QString property );
+        void chatPartnerStatusChanged();
 
 };
 
diff --git a/repos/entities/rocketchatuser.cpp b/repos/entities/rocketchatuser.cpp
index b94bb87..a4fc04b 100755
--- a/repos/entities/rocketchatuser.cpp
+++ b/repos/entities/rocketchatuser.cpp
@@ -22,7 +22,7 @@
 
 #include "rocketchatuser.h"
 
-RocketChatUser::RocketChatUser( QString pUsername ): mUserName( pUsername )
+RocketChatUser::RocketChatUser( const QString &pId ): mUserId( pId )
 {
 
 }
@@ -74,10 +74,32 @@ RocketChatUser::status RocketChatUser::getStatus() const
 
 void RocketChatUser::setStatus( status pStatus )
 {
-    mStatus = pStatus;
+    if ( pStatus != mStatus ) {
+        mStatus = pStatus;
+        emit statusChanged();
+    }
 }
 
-bool RocketChatUser::operator==(const RocketChatUser lhs)
+void RocketChatUser::setStatus( const QString &pStatus )
+{
+    if ( !pStatus.isEmpty() ) {
+        status newStatus;
+
+        if ( pStatus == "online" ) {
+            newStatus = status::ONLINE;
+        } else if ( pStatus == "away" ) {
+            newStatus = status::AWAY;
+        } else if ( pStatus == "offline" ) {
+            newStatus = status::OFFLINE;
+        } else if ( pStatus == "busy" ) {
+            newStatus = status::BUSY;
+        }
+
+        setStatus( newStatus );
+    }
+}
+
+bool RocketChatUser::operator==( const RocketChatUser lhs )
 {
     return lhs.getUserId() == this->getUserId();
 }
@@ -87,7 +109,7 @@ QString RocketChatUser::getName() const
     return mName;
 }
 
-void RocketChatUser::setName(const QString &name)
+void RocketChatUser::setName( const QString &name )
 {
     mName = name;
 }
diff --git a/repos/entities/rocketchatuser.h b/repos/entities/rocketchatuser.h
index b3e5495..61412d5 100755
--- a/repos/entities/rocketchatuser.h
+++ b/repos/entities/rocketchatuser.h
@@ -34,9 +34,10 @@ class RocketChatUser : public QObject
         enum class status {
             ONLINE,
             AWAY,
-            OFFLINE
+            OFFLINE,
+            BUSY
         };
-        explicit RocketChatUser( QString pUsername )                                            ;
+        explicit RocketChatUser( const QString &pId )                                            ;
 
         QString getUserName() const;
         void setUserName( const QString &pValue );
@@ -52,6 +53,8 @@ class RocketChatUser : public QObject
 
         status getStatus() const;
         void setStatus( status );
+        void setStatus( const QString &pStatus );
+        
 
         inline bool operator==( const RocketChatUser lhs );
 
@@ -66,7 +69,7 @@ class RocketChatUser : public QObject
         QString mName;
         status mStatus = status::OFFLINE;
     signals:
-
+        void statusChanged();
     public slots:
 };
 
diff --git a/rocketchatserver.cpp b/rocketchatserver.cpp
index 4b2e6f0..bcf16bd 100755
--- a/rocketchatserver.cpp
+++ b/rocketchatserver.cpp
@@ -1183,49 +1183,49 @@ void RocketChatServerData::onDDPMessageReceived( const QJsonObject &pMessage )
             QString msg = pMessage[QStringLiteral( "msg" )].toString();
             QJsonObject fields = pMessage["fields"].toObject();
 
-            if ( fields.contains( QStringLiteral( "username" ) ) ) {
-                auto username = fields["username"].toString();
-                auto user = userModel->getUserByUsername( username );
+            auto user = userModel->getUserById( userId );
 
-                if ( !user.isNull() ) {
-                    if ( msg == QStringLiteral( "added" ) ) {
-
-                    } else if ( msg == QStringLiteral( "changed" ) ) {
-                        if ( fields.contains( QStringLiteral( "status" ) ) ) {
-                            QString msgStatus = fields[QStringLiteral( "status" )].toString();
-                            RocketChatUser::status userStatus;
-
-                            if ( msgStatus == QStringLiteral( "online" ) ) {
-                                userStatus = RocketChatUser::status::ONLINE;
-                            } else if ( msgStatus == QStringLiteral( "away" ) ) {
-                                userStatus = RocketChatUser::status::AWAY;
-                            } else {
-                                userStatus = RocketChatUser::status::OFFLINE;
-                            }
+            if ( !user.isNull() ) {
+                if ( msg == QStringLiteral( "added" ) || msg == QStringLiteral( "changed" ) ) {
 
-                            user->setStatus( userStatus );
-                        }
+                    if ( fields.contains( QStringLiteral( "status" ) ) ) {
+                        QString msgStatus = fields[QStringLiteral( "status" )].toString();
+                        user->setStatus( msgStatus );
+                    }
 
-                    } else if ( msg == QStringLiteral( "removed" ) ) {
-                        //TODO: delete user
-                        user->setStatus( RocketChatUser::status::OFFLINE );
+                    if ( fields.contains( QStringLiteral( "name" ) ) ) {
+                        user->setUserName( fields[QStringLiteral( "name" )].toString() );
                     }
-                } else {
-                    auto newUser = QSharedPointer<RocketChatUser>( new RocketChatUser( username ) );
-                    newUser->setUserId( userId );
 
-                    if ( pMessage.contains( "fields" ) ) {
-                        QJsonObject fields = pMessage["fields"].toObject();
 
-                        if ( fields.contains( "username" ) ) {
-                            newUser->setUserName( username );
-                        }
+                } else if ( msg == QStringLiteral( "removed" ) ) {
+                    //TODO: delete user
+                    user->setStatus( RocketChatUser::status::OFFLINE );
+                }
+            } else {
+                auto newUser = QSharedPointer<RocketChatUser>( new RocketChatUser( userId ) );
+
+                if ( pMessage.contains( "fields" ) ) {
+                    QJsonObject fields = pMessage["fields"].toObject();
+
+                    if ( fields.contains( QStringLiteral( "status" ) ) ) {
+                        QString msgStatus = fields[QStringLiteral( "status" )].toString();
+                        newUser->setStatus( msgStatus );
+                    }
+
+                    if ( fields.contains( QStringLiteral( "name" ) ) ) {
+                        newUser->setName( fields[QStringLiteral( "name" )].toString() );
                     }
 
-                    QMetaObject::invokeMethod( userModel, "addUser", Q_ARG( User, newUser ) );
+                    if ( fields.contains( QStringLiteral( "username" ) ) ) {
+                        newUser->setUserName( fields[QStringLiteral( "username" )].toString() );
+                    }
                 }
+
+                QMetaObject::invokeMethod( userModel, "addUser", Q_ARG( User, newUser ) );
             }
 
+
         } else if ( pMessage[QStringLiteral( "collection" )] == QStringLiteral( "autocompleteRecords" ) ) {
             if ( Q_LIKELY( pMessage.contains( QStringLiteral( "fields" ) ) && pMessage.contains( QStringLiteral( "msg" ) ) && pMessage.contains( QStringLiteral( "id" ) ) ) ) {
                 QJsonObject fields = pMessage[QStringLiteral( "fields" )].toObject();
@@ -1857,7 +1857,8 @@ void RocketChatServerData::getLoginMethods()
     };
     QSharedPointer<RocketChatSubscribeLoginMethods> loginMethodsSubscription( new RocketChatSubscribeLoginMethods() );
     loginMethodsSubscription->setSuccess( success );
-    sendDdprequest( loginMethodsSubscription );
+    // sendDdprequest( loginMethodsSubscription );
+    mDdpApi->sendRequest( loginMethodsSubscription );
 }
 
 void RocketChatServerData::getServerInfo()
diff --git a/services/rocketchatchannelservice.cpp b/services/rocketchatchannelservice.cpp
index 202a60a..1258f8f 100755
--- a/services/rocketchatchannelservice.cpp
+++ b/services/rocketchatchannelservice.cpp
@@ -22,6 +22,8 @@
 
 #include "rocketchatchannelservice.h"
 
+#include <CustomModels/models.h>
+
 
 
 RocketChatChannelService::RocketChatChannelService( RocketChatServerData *pServer, MessageService *pMessageService )
@@ -74,7 +76,7 @@ QVector<QSharedPointer<RocketChatChannel> > RocketChatChannelService::processCha
     QString openChannel = std::get<0>( openChannelTupel );
     mStorage->transaction();
 
-    for ( const auto &currentChannel : pChannelArray ) {
+    for ( const auto currentChannel : pChannelArray ) {
         QJsonObject currentChannelObject = currentChannel.toObject();
 
         if ( Q_LIKELY( ( currentChannelObject.contains( "rid" ) &&
@@ -85,14 +87,19 @@ QVector<QSharedPointer<RocketChatChannel> > RocketChatChannelService::processCha
             QString name = currentChannelObject["name"].toString();
             QString type = currentChannelObject["t"].toString();
             QString username = "";
+            QString chatPartnerId ;
+
+            if ( id == "" ) {
+                id = currentChannelObject["_id"].toString();
+            }
 
             if ( type == "d" ) {
                 username = name;
                 name = currentChannelObject["fname"].toString();
-            }
 
-            if ( id == "" ) {
-                id = currentChannelObject["_id"].toString();
+                QString ownUser = mServer->getUserId();
+                chatPartnerId = id;
+                chatPartnerId.replace( ownUser, "" );
             }
 
             //TODO: refactor me please!
@@ -118,6 +125,8 @@ QVector<QSharedPointer<RocketChatChannel> > RocketChatChannelService::processCha
 
 
                 if ( type == "d" ) {
+                    channel->setChatPartnerId( chatPartnerId );
+
                     /* QString name = currentChannelObject["name"].toString();
                      QString fname = currentChannelObject["fname"].toString();
 
@@ -172,13 +181,12 @@ QVector<QSharedPointer<RocketChatChannel> > RocketChatChannelService::processCha
                 if ( id == openChannel ) {
                     channel->setUnreadMessages( 0 );
                 } else if ( currentChannelObject.contains( "unread" ) ) {
-                    channel->setUnreadMessages( currentChannelObject["unread"].toInt() );
+                    channel->setUnreadMessages( static_cast<unsigned int>( currentChannelObject["unread"].toInt() ) );
                 }
 
                 channel->setJoined( pJoined );
                 loadUsersOfChannel( channel );
 
-
                 if ( channel->getArchived() ) {
                     subscribeChannel( channel );
                 }
@@ -307,17 +315,51 @@ void RocketChatChannelService::loadUsersOfChannel( QSharedPointer<RocketChatChan
                 if ( Q_LIKELY( result.contains( "records" ) && result["records"].isArray() ) ) {
                     QJsonArray records = result["records"].toArray();
                     QVector<QSharedPointer<RocketChatUser>> userList;
+                    auto userModel = Models::getUsersModel();
 
                     //crate new user objects and add them to the channel
-                    for ( const auto &current : records ) {
+                    for ( const auto current : records ) {
                         if ( current.type() == QJsonValue::Object ) {
                             QJsonObject userObject = current.toObject();
                             QString username = userObject["username"].toString();
+                            QString userId = userObject["id"].toString();
+                            QString status;
+
+                            if ( userObject.contains( "status" ) ) {
+                                status = userObject["status"].toString();
+                            }
+
+                            if ( userId.isEmpty() && userObject.contains( "_id" ) ) {
+                                userId = userObject["_id"].toString();
+                            }
+
+                            QSharedPointer<RocketChatUser> user;
+
                             QString name = userObject["name"].toString();
-                            QSharedPointer<RocketChatUser> user( new RocketChatUser( username ) );
-                            user->setName( name );
+                            auto oldUser = userModel->getUserById( userId );
+
+                            if ( !oldUser.isNull() ) {
+                                oldUser->setName( name );
+                                oldUser->setUserId( username );
+                                oldUser->setStatus( status );
+                                user = oldUser;
+
+                            } else {
+                                QSharedPointer<RocketChatUser> newUser( new RocketChatUser( userId ) );
+                                newUser->setName( name );
+                                newUser->setUserName( username );
+                                newUser->setStatus( status );
+                                user = newUser;
+                            }
+
+                            if ( userId == pChannel->getChatPartnerId() ) {
+                                pChannel->setChatPartner( user );
+                            }
+
                             userList.append( user );
+
                         } else if ( current.type() == QJsonValue::String ) {
+                            //TODO: still relevant?
                             QString name = current.toString();
                             QSharedPointer<RocketChatUser> user( new RocketChatUser( name ) );
                             userList.append( user );
-- 
GitLab