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 ¤tEmoji : 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 ¤tEmoji : 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 ); + } } } }