diff --git a/api/meteorddp.cpp b/api/meteorddp.cpp
index 1266e43c706431843c5e9a20b93a36260221669a..8a130954e574cb0a089615830a7640ae9bc6d3b6 100755
--- a/api/meteorddp.cpp
+++ b/api/meteorddp.cpp
@@ -46,6 +46,7 @@ void MeteorDDP::init( const QString &pUri )
     mResponseBinding.reserve( 100 );
     connect( mWsClient, &Websocket::textMessageReceived, this, &MeteorDDP::onTextMessageReceived, Qt::UniqueConnection );
     connect( mWsClient, &Websocket::connected, this, &MeteorDDP::onConnected, Qt::UniqueConnection );
+    connect( mWsClient, &Websocket::closed, this, &MeteorDDP::ddpDisconnected );
     connect( this, &MeteorDDP::sendMessageSignal, this, &MeteorDDP::sendJson, Qt::UniqueConnection );
     mWsClient->open( wsUri );
     QDateTime now = QDateTime::currentDateTime();
diff --git a/api/meteorddp.h b/api/meteorddp.h
index 9a5dbbb17c7c9e4af954ace16bd1a3ab1cf21d3e..c584a7b4ab44aba225bc8864b037885e427fae0e 100755
--- a/api/meteorddp.h
+++ b/api/meteorddp.h
@@ -91,6 +91,7 @@ class MeteorDDP : public QObject
     signals:
         void websocketConnected();
         void ddpConnected();
+        void ddpDisconnected();
         void ddpLoginConfigured();
         void messageReceived( QJsonObject pMessage );
         void sendMessageSignal( QJsonObject );
diff --git a/api/restapi.cpp b/api/restapi.cpp
index 3fc791c58ad01db1a35133b0e7f32e56897ba857..d64a346f8bc5e6ecd7dfe564fe7b21d155ad5088 100755
--- a/api/restapi.cpp
+++ b/api/restapi.cpp
@@ -194,6 +194,11 @@ void RestApi::processNetworkRequest( QNetworkReply *pReply )
     }
 }
 
+void RestApi::slotError( QNetworkReply::NetworkError error )
+{
+    qDebug() << error;
+}
+
 
 QNetworkReply *RestApi::post( const QString &pUrl, const QByteArray &pData, const QString &pMimeType )
 {
@@ -351,6 +356,9 @@ void RestApi::sendRequestSlot( const RestApiRequest &pRequest )
             reply = post( path, pRequest->getContent(), pRequest->getMimeType() );
         }
 
+        connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ),
+                 this, SLOT( slotError( QNetworkReply::NetworkError ) ) );
+
         mResponseBinding[reply] = pRequest;
     }
 }
diff --git a/api/restapi.h b/api/restapi.h
index d9349618322b1015f4e71ac439546d67d8f120cf..346e479bdcc17bcbb37171860408e3233120c8e7 100755
--- a/api/restapi.h
+++ b/api/restapi.h
@@ -111,6 +111,8 @@ class RestApi: public QObject
         void processLogoutRequest( QNetworkReply * );
         void processNetworkRequest( QNetworkReply * );
 
+    public slots:
+        void slotError( QNetworkReply::NetworkError error );
     signals:
         void loggedIn();
         void fileDownloaded( QString pUrl, QString pTempfile );
diff --git a/rocketchatserver.cpp b/rocketchatserver.cpp
index 42dcc38814bfaa641f30c3c9b39fc7dfd8c1fb41..0b58700a7dea6565dbc390786c9c7a6b1f7e9a10 100755
--- a/rocketchatserver.cpp
+++ b/rocketchatserver.cpp
@@ -72,7 +72,7 @@ void RocketChatServerData::init()
 
     connect( mDdpApi, &MeteorDDP::messageReceived, this, &RocketChatServerData::onDDPMessageReceived, Qt::UniqueConnection );
     connect( mDdpApi, &MeteorDDP::ddpConnected, this, &RocketChatServerData::onDDPConnected, Qt::UniqueConnection );
-    qDebug() << "loaded channel list from db";
+    connect( mDdpApi, &MeteorDDP::ddpDisconnected, this, &RocketChatServerData::onDDPDisonnected, Qt::UniqueConnection );
 
     mUserId = mStorage->getUserId();
     mUsername = mStorage->getUserName();
@@ -170,8 +170,6 @@ void RocketChatServerData::loadEmojis()
             //        }
         }
     }
-
-    qDebug() << "emojis parsed";
 }
 
 void RocketChatServerData::switchChannel( const QString &pServer, const QString &pRid, const QString &pName, const QString &pType )
@@ -406,6 +404,7 @@ void RocketChatServerData::checkForMissedMessages()
 
 void RocketChatServerData::disconnectFromServer()
 {
+    mConnectionState == ConnectionState::OFFLINE;
     mDdpApi->disconnectFromServer();
 }
 
@@ -546,32 +545,34 @@ void RocketChatServerData::loginWithHash( const QString &pUsername, const QStrin
 {
     qDebug() << "login with hash";
 
+    auto self = this;
+
     QSharedPointer<DDPLoginRequest> request( new DDPLoginRequest( pUsername, pPswHash ) );
-    std::function<void ( QJsonObject, MeteorDDP * )> success = [ = ]( QJsonObject pResponse, MeteorDDP * ) {
+    std::function<void ( QJsonObject, MeteorDDP * )> success = [ self, pUsername, pPswHash, request ]( QJsonObject pResponse, MeteorDDP * ) {
         qDebug() << "authenticated";
 
         if ( pResponse.contains( QStringLiteral( "result" ) ) ) {
             QJsonObject result = pResponse[QStringLiteral( "result" )].toObject();
 
             if ( result.contains( QStringLiteral( "token" ) ) && result.contains( QStringLiteral( "id" ) ) ) {
-                mConnectionState = ConnectionState::ONLINE;
-                mResumeToken = result[QStringLiteral( "token" )].toString();
+                self->mConnectionState = ConnectionState::ONLINE;
+                self->mResumeToken = result[QStringLiteral( "token" )].toString();
                 QJsonObject expireObject = result[( "tokenExpires" )].toObject();
                 double expireDouble = expireObject[QStringLiteral( "$date" )].toDouble();
-                mTokenExpire = static_cast<uint>( expireDouble / 1000 );
+                self->mTokenExpire = static_cast<uint>( expireDouble / 1000 );
                 QString userId = result[QStringLiteral( "id" )].toString();
-                mStorage->transaction();
-                mStorage->setUserData( pUsername, pPswHash );
-                mStorage->setToken( mResumeToken, mTokenExpire );
-                mStorage->setUserId( userId );
-                mRestApi->setToken( mResumeToken );
-                mRestApi->setUserId( userId );
-                mStorage->commit();
-                this->mUserId = result[QStringLiteral( "id" )].toString();
-                mDdpApi->setToken( mResumeToken );
-                mDdpApi->unsetResponseBinding( request->getFrame() );
-                this->onDDPAuthenticated();
-                emit( onHashLoggedIn( mServerId ) );
+                self->mStorage->transaction();
+                self->mStorage->setUserData( pUsername, pPswHash );
+                self->mStorage->setToken( self->mResumeToken, self->mTokenExpire );
+                self->mStorage->setUserId( userId );
+                self->mRestApi->setToken( self->mResumeToken );
+                self->mRestApi->setUserId( userId );
+                self->mStorage->commit();
+                self->mUserId = result[QStringLiteral( "id" )].toString();
+                self->mDdpApi->setToken( self->mResumeToken );
+                self->mDdpApi->unsetResponseBinding( request->getFrame() );
+                self->onDDPAuthenticated();
+                emit( self->onHashLoggedIn( self->mServerId ) );
             }
         }
     };
@@ -582,7 +583,7 @@ void RocketChatServerData::loginWithHash( const QString &pUsername, const QStrin
 
     request->setSuccess( success );
     request->setError( error );
-    mDdpApi->sendRequest( request );
+    sendDdprequest( request, true, true );
     this->mUsername = pUsername;
 }
 
@@ -607,36 +608,32 @@ void RocketChatServerData::loginWithToken( const QString &pUsername, const QStri
         };
 
         QSharedPointer<DDPLoginRequest> request( new DDPLoginRequest( pToken ) );
-        std::function<void ( QJsonObject, MeteorDDP * )> success = [ = ]( QJsonObject pResponse, MeteorDDP * ) {
+        std::function<void ( QJsonObject, MeteorDDP * )> success = [ self, request, meCallBackSuccess ]( QJsonObject pResponse, MeteorDDP * ) {
             qDebug() << "authenticated";
-            mConnectionState = ConnectionState::ONLINE;
+            self->mConnectionState = ConnectionState::ONLINE;
 
             if ( pResponse.contains( QStringLiteral( "result" ) ) ) {
                 QJsonObject result = pResponse[QStringLiteral( "result" )].toObject();
 
                 if ( result.contains( QStringLiteral( "token" ) ) && result.contains( QStringLiteral( "id" ) ) ) {
-                    this->mResumeToken = result[QStringLiteral( "token" )].toString();
+                    self->mResumeToken = result[QStringLiteral( "token" )].toString();
                     QJsonObject expireObject = result[QStringLiteral( "tokenExpires" )].toObject();
                     double expireDouble = expireObject[QStringLiteral( "$date" )].toDouble();
-                    mTokenExpire = static_cast<uint>( expireDouble / 1000 );
+                    self->mTokenExpire = static_cast<uint>( expireDouble / 1000 );
 
                     QString userId = result[QStringLiteral( "id" )].toString();
-                    mStorage->setToken( mResumeToken, mTokenExpire );
-                    mStorage->setUserId( userId );
-                    mRestApi->setToken( mResumeToken );
-                    mRestApi->setUserId( userId );
-                    this->mUserId = result[QStringLiteral( "id" )].toString();
-                    mDdpApi->setToken( mResumeToken );
-                    mDdpApi->unsetResponseBinding( request->getFrame() );
-
+                    self->mStorage->setToken( self->mResumeToken, self->mTokenExpire );
+                    self->mStorage->setUserId( userId );
+                    self->mRestApi->setToken( self->mResumeToken );
+                    self->mRestApi->setUserId( userId );
+                    self->mUserId = result[QStringLiteral( "id" )].toString();
+                    self->mDdpApi->setToken( self-> mResumeToken );
+                    self->mDdpApi->unsetResponseBinding( request->getFrame() );
 
                     RestApiRequest meRequest
                         = RestApiRequest( new restMeRequest( meCallBackSuccess ) );
 
-                    mRestApi->sendRequest( meRequest );
-
-
-
+                    self->mRestApi->sendRequest( meRequest );
                 }
             }
         };
@@ -660,7 +657,7 @@ void RocketChatServerData::loginWithToken( const QString &pUsername, const QStri
 
         request->setSuccess( success );
         request->setError( error );
-        mDdpApi->sendRequest( request );
+        sendDdprequest( request, true, true );
         this->mUsername = pUsername;
     } else {
         qDebug() << "empty token";
@@ -726,7 +723,7 @@ void RocketChatServerData::loginWtihSamlToken( const QString &pToken )
         
         request->setSuccess( success );
         request->setError( error );
-        mDdpApi->sendRequest( request );
+        sendDdprequest( request, true, true );
     } else {
         qDebug() << "empty token";
     }
@@ -745,7 +742,6 @@ void RocketChatServerData::loginWithOpenIDToken( const QString &pToken, const QS
                 self->mStorage->setToken( self->mResumeToken, self->mTokenExpire );
                 self->mStorage->setUserId( self->mUserId );
                 self->mStorage->commit();
-                self->resume();
                 self->onResume();
                 self->onDDPAuthenticated();
             }
@@ -755,32 +751,32 @@ void RocketChatServerData::loginWithOpenIDToken( const QString &pToken, const QS
         QSharedPointer<DDPOpenIDLoginRequest> request( new DDPOpenIDLoginRequest( pToken, pSecret ) );
         std::function<void ( QJsonObject, MeteorDDP * )> success = [ = ]( QJsonObject pResponse, MeteorDDP * ) {
             qDebug() << "authenticated";
-            mConnectionState = ConnectionState::ONLINE;
+            self->mConnectionState = ConnectionState::ONLINE;
 
             if ( pResponse.contains( QStringLiteral( "result" ) ) ) {
                 QJsonObject result = pResponse[QStringLiteral( "result" )].toObject();
 
                 if ( result.contains( QStringLiteral( "token" ) ) && result.contains( QStringLiteral( "id" ) ) ) {
-                    mConnectionState = ConnectionState::ONLINE;
-                    mResumeToken = result[QStringLiteral( "token" )].toString();
+                    self->mConnectionState = ConnectionState::ONLINE;
+                    self->mResumeToken = result[QStringLiteral( "token" )].toString();
                     QJsonObject expireObject = result[QStringLiteral( "tokenExpires" )].toObject();
                     double expireDouble = expireObject[QStringLiteral( "$date" )].toDouble();
-                    mTokenExpire = static_cast<uint>( expireDouble / 1000 );
+                    self->mTokenExpire = static_cast<uint>( expireDouble / 1000 );
 
                     QString userId = result[QStringLiteral( "id" )].toString();
 
-                    mRestApi->setToken( mResumeToken );
-                    mRestApi->setUserId( userId );
-                    mUserId = result[QStringLiteral( "id" )].toString();
-                    mDdpApi->setToken( mResumeToken );
-                    mDdpApi->unsetResponseBinding( request->getFrame() );
+                    self->mRestApi->setToken( mResumeToken );
+                    self->mRestApi->setUserId( userId );
+                    self->mUserId = result[QStringLiteral( "id" )].toString();
+                    self->mDdpApi->setToken( mResumeToken );
+                    self->mDdpApi->unsetResponseBinding( request->getFrame() );
 
-                    emit( onHashLoggedIn( mServerId ) );
+                    emit self->onHashLoggedIn( self->mServerId ) ;
 
                     RestApiRequest meRequest
                         = RestApiRequest( new restMeRequest( meCallBackSuccess ) );
 
-                    mRestApi->sendRequest( meRequest );
+                    self->mRestApi->sendRequest( meRequest );
 
                 }
             }
@@ -795,7 +791,7 @@ void RocketChatServerData::loginWithOpenIDToken( const QString &pToken, const QS
 
         request->setSuccess( success );
         request->setError( error );
-        mDdpApi->sendRequest( request );
+        sendDdprequest( request, true, true );
 
     } else {
         qDebug() << "empty token";
@@ -816,7 +812,10 @@ void RocketChatServerData::loginWithMethod( const QString &method, const QString
             if ( obj.contains( QStringLiteral( "credentialToken" ) ) && obj.contains( QStringLiteral( "credentialSecret" ) ) ) {
                 token = obj[QStringLiteral( "credentialToken" )].toString();
                 secret = obj[QStringLiteral( "credentialSecret" )].toString();
+                // if app went offline during webview
+                disconnectFromServer();
                 loginWithOpenIDToken( token, secret );
+                resume();
             }
         }
     }
@@ -844,7 +843,12 @@ void RocketChatServerData::onDDPConnected()
     getLoginMethods();
     emit( ddpConnected( mServerId ) );
     mConnected = true;
+    sendUnsentMessages();
+}
 
+void RocketChatServerData::onDDPDisonnected()
+{
+    mConnectionState = ConnectionState::OFFLINE;
 }
 
 void RocketChatServerData::onDDPAuthenticated()
@@ -1034,6 +1038,19 @@ void RocketChatServerData::sendUnsentMessages()
         mUnsendRestRequests.clear();
         mUnsentMutex.unlock();
         qDebug() << "all messages send";
+    } else if ( mConnectionState == ConnectionState::CONNECTED ) {
+        mUnsentMutex.lock();
+
+        for ( const auto &request : mUnsendDdpRequestsOnConnected ) {
+            if ( !request.isNull() ) {
+                sendDdprequest( request, true, true );
+            }
+        }
+
+        mUnsendDdpRequestsOnConnected.clear();
+        qDebug() << "send unsend rest messages";
+
+        mUnsentMutex.unlock();
     }
 }
 
@@ -1068,6 +1085,8 @@ void RocketChatServerData::sendDdprequest( const QSharedPointer<DDPRequest> &pRe
             mDdpApi->sendRequest( pRequest );
         } else if ( mConnectionState == ConnectionState::CONNECTED && intime && pSendWhenConnected ) {
             mDdpApi->sendRequest( pRequest );
+        } else if ( pRetry && pSendWhenConnected ) {
+            mUnsendDdpRequestsOnConnected.append( pRequest );
         } else if ( pRetry ) {
             qDebug() << "message queued";
             mUnsendDdpRequests.append( pRequest );
@@ -1522,31 +1541,34 @@ void RocketChatServerData::getCustomEmojis()
 {
     std::function<void ( QList<QSharedPointer<Emoji>> )> success = [ = ]( QList<QSharedPointer<Emoji>> pEmojiList ) {
         QVariantList variantList;
-        mStorage->transaction();
 
-        for ( const auto &emoji : pEmojiList ) {
-            if ( !emoji.isNull() ) {
-                mEmojiService->persistEmoji( emoji );
+        if ( variantList.size() ) {
+            mStorage->transaction();
+
+            for ( const auto &emoji : pEmojiList ) {
+                if ( !emoji.isNull() ) {
+                    mEmojiService->persistEmoji( emoji );
 
-                customEmojisDirtyFlag = true;
+                    customEmojisDirtyFlag = true;
 
-                if ( !mEmojiRepo->contains( emoji->getIdentifier() ) ) {
+                    if ( !mEmojiRepo->contains( emoji->getIdentifier() ) ) {
 
-                    mEmojiRepo->add( emoji->getIdentifier(), emoji );
-                    variantList.append( emoji->toQVariantMap() );
+                        mEmojiRepo->add( emoji->getIdentifier(), emoji );
+                        variantList.append( emoji->toQVariantMap() );
 
-                    if ( emoji->getCategory() == QStringLiteral( "custom" ) ) {
-                        // mCustomEmojisHash = Utils::hash(mCustomEmojis);
+                        if ( emoji->getCategory() == QStringLiteral( "custom" ) ) {
+                            // mCustomEmojisHash = Utils::hash(mCustomEmojis);
+                        }
                     }
                 }
             }
+
+            mStorage->commit();
         }
 
-        mStorage->commit();
         emit customEmojisReceived( getEmojisByCategory() );
 
 
-
         QSharedPointer<RocketChatSubscribeUserNotify> notifySubSubscription( new RocketChatSubscribeUserNotify( this->mUserId ) );
         QSharedPointer<RocketChatNotifyNoticesRequest> notifyNoticeSubSubscription( new RocketChatNotifyNoticesRequest( this->mUserId ) );
         QSharedPointer<RocketChatSubScriptionChangedRequest> noitfySubscriptionsSubscription( new RocketChatSubScriptionChangedRequest( this->mUserId ) );
diff --git a/rocketchatserver.h b/rocketchatserver.h
index da2df078c1ade819c2b3b9983d945fadbd909bba..846fccb53543a4c3aed7ab024fcd845721502c10 100755
--- a/rocketchatserver.h
+++ b/rocketchatserver.h
@@ -273,6 +273,7 @@ class RocketChatServerData : public QObject
         FileService *mFileService = nullptr;
         QHash<QString, bool> mDownloadsInProgress;
         QLinkedList<QSharedPointer<DDPRequest>> mUnsendDdpRequests;
+        QLinkedList<QSharedPointer<DDPRequest>> mUnsendDdpRequestsOnConnected;
         QLinkedList<RestApiRequest> mUnsendRestRequests;
         QMap<QString, FileUploader *> mFileUploads;
         QString mCurrentChannel;
@@ -292,6 +293,8 @@ class RocketChatServerData : public QObject
 
         void getServerSettings( void );
         void onDDPConnected();
+        void onDDPDisonnected();
+
         void onDDPAuthenticated();
         void onDDPMessageReceived( const QJsonObject &pMessage );
         void onChannelsLoaded( const QVector<QSharedPointer<RocketChatChannel> > &pChannels );
diff --git a/services/emojiservice.cpp b/services/emojiservice.cpp
index 280b5ee254f982e86ae77fc7c667987633b7501f..8eb72ecd6d0630ee2696f0d6fa6be8e4acba90cc 100755
--- a/services/emojiservice.cpp
+++ b/services/emojiservice.cpp
@@ -83,32 +83,36 @@ void EmojiService::handleCustomEmojisReceived( EmojiData *data )
     if ( data ) {
         QJsonArray jsonArray = data->getEmojiData();
 
-        for ( const auto &currentEmoji : jsonArray ) {
-            if ( !currentEmoji.isNull() ) {
-                auto parsedEmoji = parseEmoji( currentEmoji.toObject() );
-
-                if ( !parsedEmoji.isNull() ) {
-                    mParsedCustomEmojisTemp.append( parsedEmoji );
-                    qDebug() << "emoji parsed: " << parsedEmoji->getIdentifier();
-                    QString url = QStringLiteral( "/emoji-custom/" ) + parsedEmoji->getName() + '.' + parsedEmoji->getExtension();
-                    std::function<void ( QSharedPointer<TempFile>, bool )> then = [ = ]( QSharedPointer<TempFile> file, bool ) {
-                        if ( Q_UNLIKELY( file.isNull() ) ) {
-                            qWarning() << "file is null" << parsedEmoji->getIdentifier();
-                            return;
-                        }
-
-                        QString path = Utils::getPathPrefix() + file->getFilePath();
-                        parsedEmoji->setCategory( QStringLiteral( "custom" ) );
-                        parsedEmoji->setFilePath( path );
-                        parsedEmoji->setHtml( QStringLiteral( "<img height='20' width='20' src='" ) + path + QStringLiteral( "' />" ) );
-                        data->emojisProcessed++;
-
-                        if ( data->emojisProcessed == data->emojiCounter ) {
-                            data->success( mParsedCustomEmojisTemp );
-                        }
-                    };
-                    QSharedPointer<FileRequest> fileRequest( new FileRequest( url, QStringLiteral( "emoji" ), then, true ) );
-                    mFileService->getFileRessource( fileRequest );
+        if ( jsonArray.size() == 0 ) {
+            data->success( mParsedCustomEmojisTemp );
+        } else {
+            for ( const auto &currentEmoji : jsonArray ) {
+                if ( !currentEmoji.isNull() ) {
+                    auto parsedEmoji = parseEmoji( currentEmoji.toObject() );
+
+                    if ( !parsedEmoji.isNull() ) {
+                        mParsedCustomEmojisTemp.append( parsedEmoji );
+                        qDebug() << "emoji parsed: " << parsedEmoji->getIdentifier();
+                        QString url = QStringLiteral( "/emoji-custom/" ) + parsedEmoji->getName() + '.' + parsedEmoji->getExtension();
+                        std::function<void ( QSharedPointer<TempFile>, bool )> then = [ = ]( QSharedPointer<TempFile> file, bool ) {
+                            if ( Q_UNLIKELY( file.isNull() ) ) {
+                                qWarning() << "file is null" << parsedEmoji->getIdentifier();
+                                return;
+                            }
+
+                            QString path = Utils::getPathPrefix() + file->getFilePath();
+                            parsedEmoji->setCategory( QStringLiteral( "custom" ) );
+                            parsedEmoji->setFilePath( path );
+                            parsedEmoji->setHtml( QStringLiteral( "<img height='20' width='20' src='" ) + path + QStringLiteral( "' />" ) );
+                            data->emojisProcessed++;
+
+                            if ( data->emojisProcessed == data->emojiCounter ) {
+                                data->success( mParsedCustomEmojisTemp );
+                            }
+                        };
+                        QSharedPointer<FileRequest> fileRequest( new FileRequest( url, QStringLiteral( "emoji" ), then, true ) );
+                        mFileService->getFileRessource( fileRequest );
+                    }
                 }
             }
         }