diff --git a/CustomModels/channelmodel.cpp b/CustomModels/channelmodel.cpp index 9eed39a2a295ceda6ad6a14bf1f8e787ce176972..a978070269e97970f33e99c69d3dbff8e4e4f409 100644 --- a/CustomModels/channelmodel.cpp +++ b/CustomModels/channelmodel.cpp @@ -116,6 +116,23 @@ QVariant ChannelModel::data( const QModelIndex &index, int role ) const case ChannelRoles::ownerName: return currentChannel->getOwnerName(); + + case ChannelRoles::avatarImg: { + auto avatarImg = currentChannel->getAvatarImg(); + + if ( !avatarImg.isNull() ) { + auto path = QStringLiteral( "file://" ) + avatarImg->getFilePath(); + + if ( path.endsWith( "svg" ) ) { + return "qrc:res/user-identity.svg"; + } else { + return path; + } + } else { + return ""; + } + } + } return QVariant(); @@ -158,6 +175,7 @@ QHash<int, QByteArray> ChannelModel::roleNames() const roles[static_cast<int>( ChannelRoles::ownerName )] = QByteArrayLiteral( "ownerName" ); roles[static_cast<int>( ChannelRoles::username )] = QByteArrayLiteral( "username" ); roles[static_cast<int>( ChannelRoles::userStatus )] = QByteArrayLiteral( "userStatus" ); + roles[static_cast<int>( ChannelRoles::avatarImg )] = QByteArrayLiteral( "avatarImg" ); return roles; } diff --git a/CustomModels/channelmodel.h b/CustomModels/channelmodel.h index 84e9ae1e0a120164fbeaaa294a217236218d1295..de7caa5f6d7c9338042e81e50a672853c43c5508 100644 --- a/CustomModels/channelmodel.h +++ b/CustomModels/channelmodel.h @@ -51,7 +51,8 @@ class ChannelModel : public QAbstractListModel ownerId, ownerName, username, - userStatus + userStatus, + avatarImg }; public: ChannelModel() = default; diff --git a/CustomModels/messagemodel.cpp b/CustomModels/messagemodel.cpp index 94e7c47a2a266162d0c9bb17ae327a59dc7313b6..89a065f9f09901e5b5e9faa9d6b97ca96cffa830 100644 --- a/CustomModels/messagemodel.cpp +++ b/CustomModels/messagemodel.cpp @@ -162,6 +162,27 @@ QVariant MessagesModel::data( const QModelIndex &index, int role ) const case MessageRoles::replyDate: //TODO: implement or remove! break; + + case MessageRoles::avatarImg: { + if ( messageAtIndex.isNull() ) { + return ""; + } else { + auto avatarImg = messageAtIndex->getAvatarImg(); + + if ( !avatarImg.isNull() ) { + auto path = QStringLiteral( "file://" ) + avatarImg->getFilePath(); + + if ( path.endsWith( "svg" ) ) { + return "qrc:res/user-identity.svg"; + } else { + return path; + } + } else { + return ""; + } + } + } + break; } qWarning() << "MessagesModel data not found for row"; @@ -206,7 +227,7 @@ void MessagesModel::setCurrent( const QString &value ) int MessagesModel::rowCount( const QModelIndex &parent ) const { Q_UNUSED( parent ); - qDebug() << "number of messages in model" << messagesOfCurrentChannel.count(); + // qDebug() << "number of messages in model" << messagesOfCurrentChannel.count(); int count = 0; @@ -243,6 +264,10 @@ bool MessagesModel::addChannel( const QSharedPointer<RocketChatChannel> &channel return false; } + for ( auto message : channel->getMessageRepo()->getElements() ) { + connect( message.data(), &RocketChatMessage::dataChanged, this, &MessagesModel::onDataChanged, Qt::UniqueConnection ); + } + mChannelMap.insert( id, channel ); connect( channel.data(), &RocketChatChannel::messageAdded, this, [ = ]( const QString & id, qint64 timestamp ) { Q_UNUSED( id ) @@ -280,6 +305,8 @@ QHash<int, QByteArray> MessagesModel::roleNames() const roles[static_cast<int>( MessageRoles::replyAutor )] = QByteArrayLiteral( "replyAutor" ); roles[static_cast<int>( MessageRoles::replyDate )] = QByteArrayLiteral( "replyDate" ); roles[static_cast<int>( MessageRoles::replyUrl )] = QByteArrayLiteral( "replyUrl" ); + roles[static_cast<int>( MessageRoles::avatarImg )] = QByteArrayLiteral( "avatarImg" ); + return roles; } @@ -304,6 +331,7 @@ void MessagesModel::onNewMessage( const QSharedPointer<RocketChatChannel> &chann beginInsertRows( QModelIndex(), row, row ); messagesOfCurrentChannel.insert( row, message ); mInsertCount++; + connect( message.data(), &RocketChatMessage::dataChanged, this, &MessagesModel::onDataChanged, Qt::UniqueConnection ); endInsertRows(); duplicateCheck.insert( message->getId() ); } @@ -335,6 +363,32 @@ void MessagesModel::onEndInsertList( const QString &pChannelId ) } } +void MessagesModel::onDataChanged( const QString &id, const QString &property ) +{ + int pos = 0; + bool found = false; + + //TODO: could be done with less complexity + for ( const auto ¤t : messagesOfCurrentChannel ) { + if ( current->getId() == id ) { + found = true; + break; + } + + pos++; + } + + if ( found ) { + auto roles = roleNames(); + + for ( auto it = roles.begin(); it != roles.end(); it++ ) { + if ( roles[it.key()] == property ) { + emit dataChanged( index( pos ), index( pos ), {it.key()} ); + } + } + } +} + void MessagesModel::addChannelSlot( const QSharedPointer<RocketChatChannel> &channel ) { addChannel( channel ); diff --git a/CustomModels/messagemodel.h b/CustomModels/messagemodel.h index 953709e80114cc25122982bbbb88d063995e7caf..412d3ac0306b349a584a6b5e9c98eed23668db27 100644 --- a/CustomModels/messagemodel.h +++ b/CustomModels/messagemodel.h @@ -56,7 +56,8 @@ class MessagesModel : public QAbstractListModel replyMessage, replyAutor, replyDate, - replyUrl + replyUrl, + avatarImg }; MessagesModel(); QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const; @@ -86,6 +87,8 @@ class MessagesModel : public QAbstractListModel QMutex mutex; QSet<QString> mBlockedUsers; + void onDataChanged( const QString &id, const QString &property ); + signals: void currentChannelChanged( void ); void countChanged(); diff --git a/engine.pro b/engine.pro index 51793ea1a51d7d58b01e26cedcb6b13d0232544a..e9d491fb4d590871c229ef10ba0523863b557142 100644 --- a/engine.pro +++ b/engine.pro @@ -103,7 +103,8 @@ SOURCES += api/meteorddp.cpp \ ddpRequests/rocketchatcreatepublicgrouprequest.cpp \ ddpRequests/rocketchatchangeuserpresencestatus.cpp \ ddpRequests/rocketchatsubscribeuserdata.cpp \ - CustomModels/emojismodel.cpp + CustomModels/emojismodel.cpp \ + repos/filesrepo.cpp HEADERS += \ api/meteorddp.h \ @@ -209,7 +210,8 @@ HEADERS += \ ddpRequests/rocketchatchangeuserpresencestatus.h \ ddpRequests/rocketchatchangeuserpresencedefaultstatus.h \ ddpRequests/rocketchatsubscribeuserdata.h \ - CustomModels/emojismodel.h + CustomModels/emojismodel.h \ + repos/filesrepo.h linux{ diff --git a/persistancelayer.cpp b/persistancelayer.cpp index 9940e8378cfe6df9513c062ea3cc5486ce145778..226eba46c2b431ced3788f4ccb75550e17902e70 100755 --- a/persistancelayer.cpp +++ b/persistancelayer.cpp @@ -388,23 +388,24 @@ void PersistanceLayer::transaction( ) { commitMutex.lock(); - if ( mTransactionCounter == 0 ) { - if ( !mDb.transaction() ) { - qWarning() << mDb.lastError(); - } + // if ( mTransactionCounter == 0 ) { + if ( !mDb.transaction() ) { + qWarning() << mDb.lastError(); } + // } + mTransactionCounter++; commitMutex.unlock(); } void PersistanceLayer::askForcommit() { - commitMutex.lock(); + // commitMutex.lock(); // mCommitCounter++; - commitMutex.unlock(); + // commitMutex.unlock(); commit( ); } @@ -432,8 +433,9 @@ void PersistanceLayer::commit( ) void PersistanceLayer::setUserName( const QString &pUsername ) { - transaction(); - + QSqlQuery querySetUsername; + querySetUsername.prepare( QStringLiteral( "UPDATE user_data " + "SET username=:username WHERE id=:id" ) ); querySetUsername.bindValue( QStringLiteral( ":id" ), 0 ); querySetUsername.bindValue( QStringLiteral( ":username" ), pUsername ); @@ -441,12 +443,14 @@ void PersistanceLayer::setUserName( const QString &pUsername ) qWarning() << querySetUsername.lastError(); } - askForcommit(); } void PersistanceLayer::setPassword( const QString &pPassword ) { - transaction(); + QSqlQuery querySetPassword; + querySetPassword.prepare( QStringLiteral( "UPDATE user_data " + "SET password=:password WHERE id=:id" ) ); + querySetPassword.bindValue( QStringLiteral( ":password" ), pPassword ); querySetPassword.bindValue( QStringLiteral( ":id" ), 0 ); @@ -454,12 +458,14 @@ void PersistanceLayer::setPassword( const QString &pPassword ) qWarning() << querySetPassword.lastError(); } - askForcommit(); } void PersistanceLayer::setToken( const QString &pToken, uint pExpire ) { - transaction(); + QSqlQuery querySetToken; + querySetToken.prepare( QStringLiteral( "UPDATE user_data " + "SET token=:token, token_expire=:token_expire WHERE id=:id" ) ); + querySetToken.bindValue( QStringLiteral( ":token" ), pToken ); querySetToken.bindValue( QStringLiteral( ":id" ), 0 ); querySetToken.bindValue( QStringLiteral( ":token_expire" ), pExpire ); @@ -467,13 +473,14 @@ void PersistanceLayer::setToken( const QString &pToken, uint pExpire ) if ( !querySetToken.exec() ) { qWarning() << querySetToken.lastError(); } - - askForcommit(); } void PersistanceLayer::setUserData( const QString &pUser, const QString &pPass ) { - transaction(); + QSqlQuery querySetUser; + querySetUser.prepare( QStringLiteral( "REPLACE INTO user_data " + "(id,password,username) VALUES(:id,:password,:username)" ) ); + querySetUser.bindValue( ":id", 0 ); querySetUser.bindValue( ":password", pPass ); querySetUser.bindValue( ":username", pUser ); @@ -482,8 +489,6 @@ void PersistanceLayer::setUserData( const QString &pUser, const QString &pPass ) qWarning() << querySetUser.lastError(); qWarning() << querySetUser.lastQuery(); } - - askForcommit(); } QString PersistanceLayer::addFileToTemp( const QString &pUrl, const QString &pPath ) @@ -745,20 +750,21 @@ void PersistanceLayer::createFolder( const QString &pPath ) void PersistanceLayer::setUserId( const QString &pUserId ) { - transaction(); + QSqlQuery querySetUserId; + querySetUserId.prepare( QStringLiteral( "UPDATE user_data SET user_id=:userId WHERE id=:id" ) ); querySetUserId.bindValue( QStringLiteral( ":id" ), 0 ); querySetUserId.bindValue( QStringLiteral( ":userId" ), pUserId ); if ( !querySetUserId.exec() ) { qWarning() << querySetUserId.lastError(); } - - askForcommit(); } void PersistanceLayer::setCurrentChannel( const QString &pChannelId, const QString &pChannelName ) { - transaction(); + QSqlQuery querySetChannel; + querySetChannel.prepare( QStringLiteral( "REPLACE INTO current_room" + " (id,rid,name) VALUES(:id,:rid,:name)" ) ); querySetChannel.bindValue( QStringLiteral( ":id" ), 0 ); querySetChannel.bindValue( QStringLiteral( ":rid" ), pChannelId ); @@ -767,13 +773,13 @@ void PersistanceLayer::setCurrentChannel( const QString &pChannelId, const QStri if ( !querySetChannel.exec() ) { qWarning() << querySetChannel.lastError(); } - - askForcommit(); } void PersistanceLayer::setSetting( const QString &pProperty, const QString &pValue ) { - transaction(); + QSqlQuery querySetSetting; + querySetSetting.prepare( QStringLiteral( "REPLACE INTO app_settings" + " (property,value) VALUES(:property,:value)" ) ); querySetSetting.bindValue( QStringLiteral( ":property" ), pProperty ); querySetSetting.bindValue( QStringLiteral( ":value" ), pValue ); @@ -782,18 +788,18 @@ void PersistanceLayer::setSetting( const QString &pProperty, const QString &pVal qWarning() << querySetSetting.lastQuery(); qWarning() << querySetSetting.lastError(); } - - askForcommit(); - } void PersistanceLayer::addChannel( const QString &pId, const QString &pName, const QString &pType, bool pJoined, bool pReadOnly, const QString &pMuted, bool pArchived, bool pBlocked, const QString &pUsername, const QString &pChatPartnerId ) { - transaction(); + QSqlQuery queryAddChannel; + queryAddChannel.prepare( QStringLiteral( "REPLACE INTO rooms " + "(id,name,type,joined,read_only,muted,archived,blocked,username,chat_partner_id) VALUES(:id,:name,:type,:joined,:read_only,:muted,:archived,:blocked,:username,:chat_partner_id)" ) ); + queryAddChannel.bindValue( QStringLiteral( ":id" ), pId ); queryAddChannel.bindValue( QStringLiteral( ":name" ), pName ); - queryAddChannel.bindValue( QStringLiteral( ":joined" ), pJoined ); queryAddChannel.bindValue( QStringLiteral( ":type" ), pType ); + queryAddChannel.bindValue( QStringLiteral( ":joined" ), pJoined ); queryAddChannel.bindValue( QStringLiteral( ":read_only" ), pReadOnly ); queryAddChannel.bindValue( QStringLiteral( ":muted" ), pMuted ); queryAddChannel.bindValue( QStringLiteral( ":archived" ), pArchived ); @@ -804,9 +810,11 @@ void PersistanceLayer::addChannel( const QString &pId, const QString &pName, con if ( !queryAddChannel.exec() ) { qWarning() << queryAddChannel.lastError(); + qWarning() << queryAddChannel.lastQuery(); } - askForcommit(); + queryAddChannel.finish(); + } void PersistanceLayer::addChannel( const QString &pId, const QString &pName, const QString &pType, bool pJoined, const QString &pUsername, const QString &pMchatPartnerId ) @@ -820,11 +828,17 @@ void PersistanceLayer::addChannel( const QString &pId, const QString &pName, con void PersistanceLayer::deleteChannel( const QString &pId ) { + QSqlQuery queryDeleteChannel; + queryDeleteChannel.prepare( QStringLiteral( "DELETE FROM rooms WHERE id=:id" ) ); + queryDeleteChannel.bindValue( QStringLiteral( ":id" ), pId ); if ( !queryDeleteChannel.exec() ) { qWarning() << queryDeleteChannel.lastError(); } else { + QSqlQuery queryDeleteMessagesFromChannel; + queryDeleteMessagesFromChannel.prepare( QStringLiteral( "DELETE FROM messages WHERE rid=:id" ) ); + queryDeleteMessagesFromChannel.bindValue( QStringLiteral( ":id" ), pId ); if ( !queryDeleteMessagesFromChannel.exec() ) { @@ -835,7 +849,10 @@ void PersistanceLayer::deleteChannel( const QString &pId ) void PersistanceLayer::addMessage( const QString &pId, const QString &pRid, const QString &pAuthor, qint64 pTs, const QString &pJson, const QString &pUserId ) { - transaction(); + QSqlQuery queryAddMessage; + queryAddMessage.prepare( QStringLiteral( "REPLACE INTO messages " + "(id,rid,author,ts,json,read, user_id) VALUES (:id,:rid,:author,:ts,:json,0,:user_id)" ) ); + queryAddMessage.bindValue( QStringLiteral( ":id" ), pId ); queryAddMessage.bindValue( QStringLiteral( ":rid" ), pRid ); queryAddMessage.bindValue( QStringLiteral( ":author" ), pAuthor ); @@ -850,12 +867,13 @@ void PersistanceLayer::addMessage( const QString &pId, const QString &pRid, cons qWarning() << queryAddMessage.lastError(); } - askForcommit(); } void PersistanceLayer::addFileCacheEntry( const QString &pUrl, const QString &pPath ) { - transaction(); + QSqlQuery queryAddCacheEntry; + queryAddCacheEntry.prepare( QStringLiteral( "REPLACE INTO file_cache (url,path,ts)" + " VALUES (:url,:path,:ts)" ) ); qDebug() << pUrl; qDebug() << pPath; @@ -868,8 +886,6 @@ void PersistanceLayer::addFileCacheEntry( const QString &pUrl, const QString &pP if ( !queryAddCacheEntry.exec() ) { qWarning() << queryAddCacheEntry.lastError(); } - - askForcommit(); } void PersistanceLayer::addCustomEmoji( const QString &pTag, const QString &pPath, const QString &pHtml, const QString &pCategory ) @@ -883,7 +899,10 @@ void PersistanceLayer::addCustomEmoji( const QString &pTag, const QString &pPath } void PersistanceLayer::addCustomEmoji( const QString &pTag, const QString &pPath, const QString &pHtml, const QString &pCategory, const QString &pUnicode, int pOrder ) { - transaction(); + QSqlQuery queryAddEmoji; + queryAddEmoji.prepare( QStringLiteral( "REPLACE INTO custom_emojis (id,file,html,unicode,category,sort_order)" + " VALUES (:id,:file,:html,:unicode,:category,:sort_order)" ) ); + queryAddEmoji.bindValue( QStringLiteral( ":id" ), pTag ); queryAddEmoji.bindValue( QStringLiteral( ":file" ), pPath ); queryAddEmoji.bindValue( QStringLiteral( ":html" ), pHtml ); @@ -894,13 +913,12 @@ void PersistanceLayer::addCustomEmoji( const QString &pTag, const QString &pPath if ( !queryAddEmoji.exec() ) { qWarning() << queryAddEmoji.lastError(); } - - askForcommit(); } void PersistanceLayer::addUserToBlockList( const QString &pUserId, const QString &pUsername ) { - transaction(); + QSqlQuery queryAddUser; + queryAddUser.prepare( QStringLiteral( "INSERT INO blocked_users(id, author) VALUES(:id,:author)" ) ); queryAddUser.bindValue( ":id", pUserId ); queryAddUser.bindValue( ":author", pUsername ); @@ -908,13 +926,15 @@ void PersistanceLayer::addUserToBlockList( const QString &pUserId, const QString qWarning() << queryAddUser.lastError(); } - askForcommit(); } QHash<QString, QString> PersistanceLayer::getMessageByid( const QString &pId ) { + QSqlQuery queryGetMessageByRid; + queryGetMessageByRid.prepare( QStringLiteral( "SELECT * FROM messages LEFT JOIN blocked_users ON (messages.user_id=blocked_users.user_id) WHERE blocked_users.user_id IS NULL AND id=:id" ) ); + queryGetMessageByRid.bindValue( QStringLiteral( ":id" ), pId ); QHash<QString, QString> row; @@ -947,6 +967,8 @@ QHash<QString, QString> PersistanceLayer::getMessageByid( const QString &pId ) QString PersistanceLayer::getUserName() { + QSqlQuery queryGetName; + queryGetName.prepare( QStringLiteral( "SELECT username FROM user_data WHERE id=0" ) ); QString name = ""; @@ -970,6 +992,9 @@ std::tuple<QString, QString> PersistanceLayer::getCurrentChannel() QString id; QString name; + QSqlQuery queryGetCurrentChannel; + queryGetCurrentChannel.prepare( QStringLiteral( "SELECT * FROM current_room WHERE id=0" ) ); + if ( !queryGetCurrentChannel.exec() ) { qWarning() << queryGetCurrentChannel.lastError(); } else { @@ -987,6 +1012,9 @@ QString PersistanceLayer::getPassword() { QString pass = ""; + QSqlQuery queryGetPass; + queryGetPass.prepare( QStringLiteral( "SELECT password FROM user_data WHERE id=0" ) ); + if ( !queryGetPass.exec() ) { qWarning() << queryGetPass.lastError(); } else { @@ -1008,6 +1036,9 @@ QPair<QString, uint> PersistanceLayer::getToken() // getToken.bindValue( ":id", 0 ); QPair<QString, uint> token; + QSqlQuery queryGetToken; + queryGetToken.prepare( QStringLiteral( "SELECT token, token_expire FROM user_data WHERE id=0" ) ); + if ( !queryGetToken.exec() ) { qDebug() << queryGetToken.lastError(); } else { @@ -1027,6 +1058,9 @@ QPair<QString, uint> PersistanceLayer::getToken() QString PersistanceLayer::getUserId() { + QSqlQuery queryGetUserId; + queryGetUserId.prepare( "SELECT id,user_id FROM user_data WHERE id=0" ); + //getUserId.addBindValue( ":id", 0 ); QString userId; @@ -1047,6 +1081,9 @@ QString PersistanceLayer::getUserId() QList<QJsonObject> PersistanceLayer::getMessagesByRid( const QString &pRid ) { + QSqlQuery queryGetMessagesByRid; + queryGetMessagesByRid.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid ORDER BY ts DESC LIMIT 20" ) ); + queryGetMessagesByRid.bindValue( QStringLiteral( ":rid" ), pRid ); QList<QJsonObject> rows; @@ -1082,6 +1119,9 @@ QList<QJsonObject> PersistanceLayer::getMessagesByRid( const QString &pRid ) QList<QJsonObject> PersistanceLayer::getMessagesByRid( const QString &pRid, qint64 pFrom, qint64 pTo ) { + QSqlQuery queryGetMessageByRidAndRange; + queryGetMessageByRidAndRange.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid AND ts<=:from AND ts>=:to ORDER BY ts DESC LIMIT 50" ) ); + queryGetMessageByRidAndRange.bindValue( QStringLiteral( ":rid" ), pRid ); queryGetMessageByRidAndRange.bindValue( QStringLiteral( ":from" ), static_cast<qint64>( pFrom / 1000 ) ); queryGetMessageByRidAndRange.bindValue( QStringLiteral( ":to" ), static_cast<qint64>( pTo / 1000 ) ); @@ -1118,6 +1158,9 @@ QList<QJsonObject> PersistanceLayer::getMessagesByRid( const QString &pRid, qint QList<QJsonObject > PersistanceLayer::getMessagesByRid( const QString &pRid, qint64 pFrom, int pLimit ) { + QSqlQuery queryGetMessagesByRidLimit; + queryGetMessagesByRidLimit.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid AND ts<=:from ORDER BY ts DESC LIMIT :limit" ) ); + queryGetMessagesByRidLimit.bindValue( QStringLiteral( ":rid" ), pRid ); queryGetMessagesByRidLimit.bindValue( QStringLiteral( ":from" ), static_cast<qint64>( pFrom ) ); queryGetMessagesByRidLimit.bindValue( QStringLiteral( ":limit" ), pLimit ); @@ -1161,6 +1204,8 @@ QList<QJsonObject > PersistanceLayer::getMessagesByRid( const QString &pRid, qin QList<QPair<QString, QString >> PersistanceLayer::getListOfBlockedUsers() { QList<QPair<QString, QString >> retList; + QSqlQuery queryGetBlockedUsers; + queryGetBlockedUsers.prepare( QStringLiteral( "SELECT * FROM blocked_users" ) ); if ( !queryGetBlockedUsers.exec() ) { qWarning() << "getList of blocked users "; @@ -1188,6 +1233,9 @@ QList<QVariantHash> PersistanceLayer::getChannels( ) QList<QVariantHash> roomsList; roomsList.reserve( 100 ); + QSqlQuery queryGetChannels; + queryGetChannels.prepare( QStringLiteral( "SELECT * FROM rooms LEFT JOIN (SELECT DISTINCT rid FROM messages ORDER BY ts DESC) AS sub ON rooms.id = sub.rid " ) ); + if ( !queryGetChannels.exec() ) { qWarning() << queryGetChannels.lastError(); } else { @@ -1232,6 +1280,9 @@ QList< QHash<QString, QString > > PersistanceLayer::getCustomEmojis() QList<QHash<QString, QString> > returnList; returnList.reserve( 3000 ); + QSqlQuery queryGetEmojies; + queryGetEmojies.prepare( QStringLiteral( "SELECT id,file,html,category,unicode,sort_order FROM custom_emojis ORDER BY sort_order ASC" ) ); + if ( !queryGetEmojies.exec() ) { qWarning() << queryGetEmojies.lastError(); } else { @@ -1262,8 +1313,41 @@ QList< QHash<QString, QString > > PersistanceLayer::getCustomEmojis() return returnList; } + +QList<QHash<QString, QString>> PersistanceLayer::getFiles() +{ + QList<QHash<QString, QString> > returnList; + + QSqlQuery queryGetFileCacheEntry; + queryGetFileCacheEntry.prepare( QStringLiteral( "SELECT path FROM file_cache WHERE url=:url" ) ); + + QSqlQuery getFilesQuery; + getFilesQuery.prepare( "SELECT path,url FROM file_cache " ); + + if ( !getFilesQuery.exec() ) { + qWarning() << getFilesQuery.lastError(); + } else { + QSqlRecord rec = getFilesQuery.record(); + int pathCol = rec.indexOf( QStringLiteral( "path" ) ); + int urlCol = rec.indexOf( QStringLiteral( "url" ) ); + + while ( getFilesQuery.next() ) { + QHash<QString, QString> entry; + entry[QStringLiteral( "path" )] = getFilesQuery.value( pathCol ).toString(); + entry[QStringLiteral( "url" )] = getFilesQuery.value( urlCol ).toString(); + + returnList.append( entry ); + } + } + + return returnList; +} + QString PersistanceLayer::getFileCacheEntry( const QString &pUrl ) { + QSqlQuery queryGetSetting; + queryGetSetting.prepare( QStringLiteral( "SELECT property,value FROM app_settings WHERE property=:property" ) ); + queryGetFileCacheEntry.bindValue( QStringLiteral( ":url" ), pUrl ); QString returnString = ""; @@ -1294,6 +1378,9 @@ QString PersistanceLayer::getFileCacheEntry( const QString &pUrl ) QString PersistanceLayer::getSetting( const QString &pProperty ) { + QSqlQuery queryRemoveFileCacheEntry; + queryRemoveFileCacheEntry.prepare( QStringLiteral( "DELETE FROM file_cache WHERE url=:url" ) ); + queryGetSetting.bindValue( QStringLiteral( ":property" ), pProperty ); QString returnString = ""; @@ -1456,46 +1543,7 @@ void PersistanceLayer::init() void PersistanceLayer::initQueries() { - querySetUsername.prepare( QStringLiteral( "UPDATE user_data " - "SET username=:username WHERE id=:id" ) ); - querySetPassword.prepare( QStringLiteral( "UPDATE user_data " - "SET password=:password WHERE id=:id" ) ); - querySetToken.prepare( QStringLiteral( "UPDATE user_data " - "SET token=:token, token_expire=:token_expire WHERE id=:id" ) ); - querySetUser.prepare( QStringLiteral( "REPLACE INTO user_data " - "(id,password,username) VALUES(:id,:password,:username)" ) ); - querySetUserId.prepare( QStringLiteral( "UPDATE user_data SET user_id=:userId WHERE id=:id" ) ); - querySetChannel.prepare( QStringLiteral( "REPLACE INTO current_room" - " (id,rid,name) VALUES(:id,:rid,:name)" ) ); - querySetSetting.prepare( QStringLiteral( "REPLACE INTO app_settings" - " (property,value) VALUES(:property,:value)" ) ); - queryAddChannel.prepare( QStringLiteral( "REPLACE INTO rooms " - "(id,name,type,joined,read_only,muted,archived,blocked,username,chat_partner_id) VALUES(:id,:name,:type,:joined,:read_only,:muted,:archived,:blocked,:username,:chat_partner_id)" ) ); - queryDeleteChannel.prepare( QStringLiteral( "DELETE FROM rooms WHERE id=:id" ) ); - queryDeleteMessagesFromChannel.prepare( QStringLiteral( "DELETE FROM messages WHERE rid=:id" ) ); - queryAddMessage.prepare( QStringLiteral( "REPLACE INTO messages " - "(id,rid,author,ts,json,read, user_id) VALUES (:id,:rid,:author,:ts,:json,0,:user_id)" ) ); - queryAddCacheEntry.prepare( QStringLiteral( "REPLACE INTO file_cache (url,path,ts)" - " VALUES (:url,:path,:ts)" ) ); - queryAddEmoji.prepare( QStringLiteral( "REPLACE INTO custom_emojis (id,file,html,unicode,category,sort_order)" - " VALUES (:id,:file,:html,:unicode,:category,:sort_order)" ) ); - queryAddUser.prepare( QStringLiteral( "INSERT INO blocked_users(id, author) VALUES(:id,:author)" ) ); - queryGetMessageByRid.prepare( QStringLiteral( "SELECT * FROM messages LEFT JOIN blocked_users ON (messages.user_id=blocked_users.user_id) WHERE blocked_users.user_id IS NULL AND id=:id" ) ); - queryGetName.prepare( QStringLiteral( "SELECT username FROM user_data WHERE id=0" ) ); - queryGetCurrentChannel.prepare( QStringLiteral( "SELECT * FROM current_room WHERE id=0" ) ); - queryGetPass.prepare( QStringLiteral( "SELECT password FROM user_data WHERE id=0" ) ); - queryGetToken.prepare( QStringLiteral( "SELECT token, token_expire FROM user_data WHERE id=0" ) ); - queryGetUserId.prepare( "SELECT id,user_id FROM user_data WHERE id=0" ); - queryGetMessagesByRid.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid ORDER BY ts DESC LIMIT 20" ) ); - queryGetMessageByRidAndRange.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid AND ts<=:from AND ts>=:to ORDER BY ts DESC LIMIT 50" ) ); - queryGetMessagesByRidLimit.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid AND ts<=:from ORDER BY ts DESC LIMIT :limit" ) ); - queryGetBlockedUsers.prepare( QStringLiteral( "SELECT * FROM blocked_users" ) ); - queryGetChannels.prepare( QStringLiteral( "SELECT * FROM rooms LEFT JOIN (SELECT DISTINCT rid FROM messages ORDER BY ts DESC) AS sub ON rooms.id = sub.rid " ) ); - queryGetEmojies.prepare( QStringLiteral( "SELECT id,file,html,category,unicode,sort_order FROM custom_emojis ORDER BY sort_order ASC" ) ); - queryGetFileCacheEntry.prepare( QStringLiteral( "SELECT path FROM file_cache WHERE url=:url" ) ); - queryGetSetting.prepare( QStringLiteral( "SELECT property,value FROM app_settings WHERE property=:property" ) ); - queryRemoveFileCacheEntry.prepare( QStringLiteral( "DELETE FROM file_cache WHERE url=:url" ) ); } diff --git a/persistancelayer.h b/persistancelayer.h index bf107ed8be791c90c41a4dee3c8a318e7d188b7c..b197bc82d38448129aa4aff357c93914d85e0587 100755 --- a/persistancelayer.h +++ b/persistancelayer.h @@ -78,6 +78,7 @@ class PersistanceLayer : public QObject Q_INVOKABLE QString getNewImagePath( void ); QString getFileCacheEntry( const QString &pUrl ); + QList< QHash<QString, QString>> getFiles(); Q_INVOKABLE QString getSetting( const QString &pProperty ); diff --git a/repos/entities/rocketchatattachment.h b/repos/entities/rocketchatattachment.h index 97d6d11b39316ccf77e2fcdd7b05751a4b6f92f3..035e97138faca39c9cdd027466f7beb15c4125e7 100644 --- a/repos/entities/rocketchatattachment.h +++ b/repos/entities/rocketchatattachment.h @@ -24,9 +24,8 @@ #include <QString> #include <QObject> -class RocketChatAttachment : public QObject +class RocketChatAttachment { - Q_OBJECT public: RocketChatAttachment( const QString &pFileUrl, const QString &pType, const QString &pTitle ); diff --git a/repos/entities/rocketchatchannel.cpp b/repos/entities/rocketchatchannel.cpp index 2538f7850a61d1f79fbd67c667b3376594b32e26..817c58fafea5e0c1ffabb058287bdbd230b79289 100755 --- a/repos/entities/rocketchatchannel.cpp +++ b/repos/entities/rocketchatchannel.cpp @@ -309,6 +309,20 @@ void RocketChatChannel::setChatPartnerId( const QString &chatPartnerId ) { mChatPartnerId = chatPartnerId; } + +QSharedPointer<TempFile> RocketChatChannel::getAvatarImg() const +{ + return mAvatarImg; +} + +void RocketChatChannel::setAvatarImg( const QSharedPointer<TempFile> &pAvatar ) +{ + if ( mAvatarImg != pAvatar ) { + mAvatarImg = pAvatar; + emit dataChanged( mRoomId, "avatarImg" ); + } +} + bool RocketChatChannel::getBlocked() const { return mBlocked; diff --git a/repos/entities/rocketchatchannel.h b/repos/entities/rocketchatchannel.h index 771df520635eb3c09716e7e3c6ea46366c759b23..ace0fdca1db3dff85b1e5c7fbce345d886bd9693 100755 --- a/repos/entities/rocketchatchannel.h +++ b/repos/entities/rocketchatchannel.h @@ -128,7 +128,11 @@ class RocketChatChannel : public QObject const QString &getChatPartnerId() const; void setChatPartnerId( const QString &chatPartnerId ); + QSharedPointer<TempFile> getAvatarImg() const; + void setAvatarImg( const QSharedPointer<TempFile> &pAvatar ); + private: + QSharedPointer<TempFile> mAvatarImg; QString mOwnerName; QString mOwnerId; bool mDeleted; diff --git a/repos/entities/rocketchatmessage.cpp b/repos/entities/rocketchatmessage.cpp index 2f68f0d69c9a465202f2952364febd1e27ce3c0e..0799a6f56bcf36f132c8006d798d67c362664aca 100755 --- a/repos/entities/rocketchatmessage.cpp +++ b/repos/entities/rocketchatmessage.cpp @@ -197,3 +197,16 @@ void RocketChatMessage::setRoomeTyp( const QString &value ) { roomeTyp = value; } + +QSharedPointer<TempFile> RocketChatMessage::getAvatarImg() const +{ + return mAvatarImg; +} + +void RocketChatMessage::setAvatarImg( const QSharedPointer<TempFile> &avatarImg ) +{ + if ( mAvatarImg != avatarImg ) { + mAvatarImg = avatarImg; + emit dataChanged( id, "avatarImg" ); + } +} diff --git a/repos/entities/rocketchatmessage.h b/repos/entities/rocketchatmessage.h index 0016844f9dd6ca22c5db8f81ed4145e6b097e447..f5b06e152bedfa9e716f5281ca4167cd3e8dd4c5 100755 --- a/repos/entities/rocketchatmessage.h +++ b/repos/entities/rocketchatmessage.h @@ -29,11 +29,13 @@ #include "repos/emojirepo.h" #include "utils.h" #include "rocketchatattachment.h" +#include "rocketchatuser.h" class EmojiRepo; -class RocketChatMessage +class RocketChatMessage: public QObject { + Q_OBJECT public: enum class Type { textmessage, @@ -97,7 +99,12 @@ class RocketChatMessage const QString &getRoomeTyp() const; void setRoomeTyp( const QString &value ); + QSharedPointer<TempFile> getAvatarImg() const; + void setAvatarImg( const QSharedPointer<TempFile> &avatarImg ); + protected: + QSharedPointer<TempFile> mAvatarImg; + QSharedPointer<RocketChatUser> mAuthor; bool empty = false; qint64 timestamp = 0; QJsonObject data; @@ -117,6 +124,8 @@ class RocketChatMessage QString roomeTyp; QList<QSharedPointer<RocketChatAttachment>> attachments; qint64 mEmojiHash = 0; + signals: + void dataChanged( const QString &id, const QString &property ); }; #endif // ROCKETCHATMESSAGE_H diff --git a/repos/entities/rocketchatreplymessage.h b/repos/entities/rocketchatreplymessage.h index 417ea45fa66562e70e56de0b7db703daffb5dd10..3c05beae76c2a43d8747a2315b6e60f041ec88e8 100644 --- a/repos/entities/rocketchatreplymessage.h +++ b/repos/entities/rocketchatreplymessage.h @@ -6,16 +6,12 @@ #include <QObject> -class RocketChatReplyMessage : public RocketChatAttachment, RocketChatMessage +class RocketChatReplyMessage : public RocketChatAttachment, public RocketChatMessage { - Q_OBJECT public: RocketChatReplyMessage( const QString &pText, const QString &pAuthor, const QString &pUrl = "" ); using RocketChatMessage::getMessageString; using RocketChatMessage::getAuthor; - signals: - - public slots: }; #endif // ROCKETCHATREPLYMESSAGE_H diff --git a/repos/entities/rocketchatuser.h b/repos/entities/rocketchatuser.h index cd0f3b8345c550c9ba505bc438a0843ec204a875..ba73d9d9121c8ef44cdb6427edfad5ea4d41ede9 100755 --- a/repos/entities/rocketchatuser.h +++ b/repos/entities/rocketchatuser.h @@ -24,6 +24,8 @@ #define ROCKETCHATUSER_H #include <QObject> +#include <QSharedPointer> +#include "tempfile.h" class RocketChatUser : public QObject { @@ -68,8 +70,10 @@ class RocketChatUser : public QObject QString mUserId; QString mName; status mStatus = status::OFFLINE; + QSharedPointer<TempFile> mAvatarImg; signals: void statusChanged(); + void avatarChanged(); public slots: }; diff --git a/repos/filesrepo.cpp b/repos/filesrepo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b9e95192b8917eab47460d590b1257fc5d168722 --- /dev/null +++ b/repos/filesrepo.cpp @@ -0,0 +1,6 @@ +#include "filesrepo.h" + +FilesRepo::FilesRepo( QObject *parent ): QObject( parent ) +{ + mElements.reserve( 3000 ); +} diff --git a/repos/filesrepo.h b/repos/filesrepo.h new file mode 100644 index 0000000000000000000000000000000000000000..d2fc57d323997acf7eaa8839d64c31c9f560f2fa --- /dev/null +++ b/repos/filesrepo.h @@ -0,0 +1,15 @@ +#ifndef FILESREPO_H +#define FILESREPO_H + +#include <QObject> +#include "abstractbaserepository.h" +#include "repos/entities/tempfile.h" + +class FilesRepo : public QObject, public AbstractBaseRepository<TempFile> +{ + Q_OBJECT + public: + explicit FilesRepo( QObject *parent = nullptr ); +}; + +#endif // FILESREPO_H diff --git a/rocketchat.cpp b/rocketchat.cpp index ea457e94508ac482db29ac91ed58031347310568..4d928b97d59c1b532b0926ff5c72f25c3e50e728 100755 --- a/rocketchat.cpp +++ b/rocketchat.cpp @@ -642,10 +642,10 @@ void RocketChat::onLogout( const QString &pServerId ) void RocketChat::onUnreadCountChanged( const QString &pServerId, uint pUnread ) { - + static int lastUnreadCount = -1; mUnreadSum[pServerId] = pUnread; - qDebug() << "onUnreadCountChanged"; + // qDebug() << "onUnreadCountChanged"; uint number = 0; if ( mServerStatus ) { @@ -653,15 +653,18 @@ void RocketChat::onUnreadCountChanged( const QString &pServerId, uint pUnread ) number += count; } - qDebug() << "set Unread Badges to:" << number; + if ( lastUnreadCount != number ) { + + qDebug() << "set Unread Badges to:" << number; #ifdef Q_OS_ANDROID - AndroidBadges::setNumber( number ); + AndroidBadges::setNumber( number ); #endif #ifdef Q_OS_IOS - emit setBadge( number ); + emit setBadge( number ); #endif - + lastUnreadCount = number; + } } } @@ -899,6 +902,8 @@ void RocketChat::onApplicationStateChanged( const Qt::ApplicationState &pState ) for ( auto server : mServerMap ) { QMetaObject::invokeMethod( server, "setUserPresenceStatus", Q_ARG( int, 2 ) ); QMetaObject::invokeMethod( server, "disconnectFromServer" ); + QMetaObject::invokeMethod( server, "onStateChanged", Q_ARG( Qt::ApplicationState, pState ) ); + } } diff --git a/rocketchatserver.cpp b/rocketchatserver.cpp index 98cbd7f9ee937231a8cd15b11ac1046e148eaf94..93293c13ba0620bbbc724a0cb3b5e441a561bd1f 100755 --- a/rocketchatserver.cpp +++ b/rocketchatserver.cpp @@ -28,11 +28,12 @@ RocketChatServerData::RocketChatServerData( QString pId, QString pBaseUrl, bool { qRegisterMetaType<User>( "User" ); qRegisterMetaType<QList<QSharedPointer<Emoji>>>( "QList<QSharedPointer<Emoji>>" ); - + connect( this, &RocketChatServerData::destroyed, this, &RocketChatServerData::persistData, Qt::UniqueConnection ); mUnsecureConnection = pUnsecure; mApiUri = QStringLiteral( "/api/v1" ); mEmojiRepo = new EmojiRepo( this ); + mFilesRepo = new FilesRepo( this ); } @@ -63,7 +64,7 @@ void RocketChatServerData::initConnections() if ( Q_LIKELY( mChannels->contains( it.key() ) && !mChannels->get( it.key() ).isNull() ) ) { MessageList messageList = messages->values( it.key() ); mChannels->get( it.key() )->addMessages( messageList ); - mMessageService->persistMessages( messageList ); + // mMessageService->persistMessages( messageList ); } } } @@ -110,7 +111,7 @@ void RocketChatServerData::initConnections() setRestApi( new RestApi( this, protocol + mBaseUrl ) ); mFileService = new FileService( this ); - mEmojiService = new EmojiService( this, mFileService, mStorage ); + mEmojiService = new EmojiService( this, mFileService ); mDdpApi = new MeteorDDP( this, mBaseUrl, mUnsecureConnection ); @@ -141,8 +142,8 @@ void RocketChatServerData::initConnections() loadEmojis(); - mMessageService = new MessageService( this, mStorage, this, mEmojiRepo ); - mChannelService = new RocketChatChannelService( this, this, mMessageService ); + mMessageService = new MessageService( this, mStorage, this, mEmojiRepo, mFileService ); + mChannelService = new RocketChatChannelService( this, this, mMessageService, mFileService ); mChannelService->setDdp( mDdpApi ); mChannelService->setChannels( mChannels ); connect( mChannelService, &RocketChatChannelService::channelsLoaded, this, &RocketChatServerData::onChannelsLoaded, Qt::UniqueConnection ); @@ -377,6 +378,10 @@ void RocketChatServerData::onStateChanged( const Qt::ApplicationState &pState ) } else { setUserPresenceStatus( static_cast<int>( RocketChatUser::status::ONLINE ) ); } + + if ( pState == Qt::ApplicationState::ApplicationSuspended || pState == Qt::ApplicationState::ApplicationInactive ) { + persistData(); + } } void RocketChatServerData::createVideoCall( const QString &pRid ) @@ -1677,7 +1682,7 @@ void RocketChatServerData::loadRecentHistory( const QString &pChannelId ) auto messageList = messages->values( pChannelId ); qDebug() << "load recent history successfull loaded " << messageList.size(); mChannels->get( pChannelId )->addMessages( messageList ); - mMessageService->persistMessages( messageList ); + // mMessageService->persistMessages( messageList ); delete messages; } @@ -1707,7 +1712,7 @@ void RocketChatServerData::getCustomEmojis() for ( auto &emoji : pEmojiList ) { if ( !emoji.isNull() ) { if ( !mEmojiRepo->contains( emoji->getIdentifier() ) ) { - mEmojiService->persistEmoji( emoji ); + //mEmojiService->persistEmoji( emoji ); mEmojiRepo->add( emoji->getIdentifier(), emoji ); newEmojis.append( std::move( emoji ) ); } @@ -1998,7 +2003,20 @@ void RocketChatServerData::addUsersToChannel( const QString &pChannelId, const Q } } +void RocketChatServerData::persistData() +{ + mMessageService->persist(); + mChannelService->persist(); + mEmojiService->persist(); +} + + ChannelRepository *RocketChatServerData::getChannels() const { return mChannels; } + +FilesRepo *RocketChatServerData::getFiles() const +{ + return mFilesRepo; +} diff --git a/rocketchatserver.h b/rocketchatserver.h index e9b210db03978e328de6aa4c9243f38c11b06038..de2a37b5a93aea409318e415a422195e371b4d19 100755 --- a/rocketchatserver.h +++ b/rocketchatserver.h @@ -78,6 +78,7 @@ #include "services/requests/loadhistoryservicerequest.h" #include "services/fileservice.h" #include "repos/emojirepo.h" +#include "repos/filesrepo.h" #include "rocketchatserverconfig.h" #include "repos/channelrepository.h" #include "services/emojiservice.h" @@ -120,6 +121,7 @@ class RocketChatServerData : public MessageListener void setServerId( const QString &pValue ); + void persistData(); public slots: void init(); @@ -221,6 +223,7 @@ class RocketChatServerData : public MessageListener void getCustomEmojis(); RestApi *getRestApi() const; ChannelRepository *getChannels() const; + FilesRepo *getFiles() const; RocketChatChannelService *mChannelService = nullptr; void handleChannelMessage( const QJsonObject &pMessage ); uint diffToLastDDPPing(); @@ -239,6 +242,7 @@ class RocketChatServerData : public MessageListener void setUserId( const QString &userId ); EmojiRepo *getEmojiRepo() const; + void setEmojiRepo( EmojiRepo *emojiRepo ); void createAccount( const QString &username, const QString &email, const QString &password ); @@ -266,6 +270,7 @@ class RocketChatServerData : public MessageListener LoginMethodsRepository mLoginMethodRepo; ChannelRepository *mChannels = nullptr; EmojiRepo *mEmojiRepo = nullptr; + FilesRepo *mFilesRepo = nullptr; RocketChatServerConfig config; bool mConnected = false; bool mLoggedIn = false; diff --git a/services/emojiservice.cpp b/services/emojiservice.cpp index be92b87d3a80a9f82373fbea498ca15e19f966dd..1fd617bc28bc88ca83cf7193ce3cf52a11ef6f43 100755 --- a/services/emojiservice.cpp +++ b/services/emojiservice.cpp @@ -29,8 +29,8 @@ -EmojiService::EmojiService( RocketChatServerData *server, FileService *pFileService, PersistanceLayer *storage ) - : server( server ), storage( storage ), mFileService( pFileService ) +EmojiService::EmojiService( RocketChatServerData *server, FileService *pFileService ) + : server( server ), storage( PersistanceLayer::instance() ), mFileService( pFileService ) { mParsedCustomEmojisTemp.reserve( 50 ); } @@ -78,6 +78,18 @@ void EmojiService::persistEmoji( const QSharedPointer<Emoji> &pEmoji ) storage->addCustomEmoji( pEmoji->getIdentifier(), pEmoji->getFilePath(), pEmoji->getHtml(), QStringLiteral( "custom" ), QStringLiteral( "dontcare" ) ); } +void EmojiService::persist() +{ + storage->transaction(); + auto emojiRepo = server->getEmojiRepo(); + + for ( const auto &emoji : emojiRepo->getElements() ) { + persistEmoji( emoji ); + } + + storage->askForcommit(); +} + void EmojiService::handleCustomEmojisReceived( EmojiData *data ) { if ( data ) { diff --git a/services/emojiservice.h b/services/emojiservice.h index 37080002424dc53f7d8751e4b3db1cbf19f26a7e..bcccf346d50ce6f8599d6028c738c0ffc61b8f96 100644 --- a/services/emojiservice.h +++ b/services/emojiservice.h @@ -49,11 +49,12 @@ class EmojiData class EmojiService { public: - EmojiService( RocketChatServerData *server, FileService *pFileService, PersistanceLayer *storage ); + EmojiService( RocketChatServerData *server, FileService *pFileService ); void loadCustomEmojis( std::function<void ( QList<QSharedPointer<Emoji>> )> success ); QList<QSharedPointer<Emoji>> loadEmojisFromDb( void ); void persistEmoji( const QSharedPointer<Emoji> &pEmoji ); - protected: + void persist(); + private: RocketChatServerData *server; void handleCustomEmojisReceived( EmojiData *data ); QSharedPointer<Emoji> parseEmoji( const QHash<QString, QString> &pEmojiData ); diff --git a/services/fileservice.cpp b/services/fileservice.cpp index 6394d99a0b7536ebaa554313303b14397fad62f2..768e8e569744ec5fea1f5413c479f71ba274c551 100755 --- a/services/fileservice.cpp +++ b/services/fileservice.cpp @@ -52,6 +52,7 @@ FileService::FileService( RocketChatServerData *server ) } mServer = server; + getFilesFromDb(); } } @@ -127,27 +128,50 @@ bool FileService::getFileRessource( const QSharedPointer< FileRequest > &pReques return false; } +void FileService::getFilesFromDb() +{ + auto files = mStorage->getFiles(); + auto repo = mServer->getFiles(); + + for ( const auto &file : files ) { + auto url = file["url"]; + auto path = file["path"]; + repo->add( url, QSharedPointer<TempFile>::create( path, url ) ); + } +} + QSharedPointer<TempFile> FileService::getFileFromCache( const QSharedPointer< FileRequest > &pRequest ) { if ( !pRequest.isNull() ) { + auto repo = mServer->getFiles(); + + if ( repo == nullptr ) { + qDebug() << "repo is null"; + } + QString baseUrl = mServer->getRestApi()->getBaseUrl(); QString fullUrl = baseUrl + pRequest->url ; qDebug() << "file from cache requested" << fullUrl; - QString storageEntry = mStorage->getFileCacheEntry( fullUrl ); - qDebug() << "cachehit:" << fullUrl << ":" << storageEntry; - qDebug() << "storageEntry len " << storageEntry.size(); - if ( !storageEntry.size() ) { - return QSharedPointer<TempFile>( nullptr ); - } + if ( repo->contains( fullUrl ) ) { + auto storageEntry = repo->get( fullUrl ); - QFile cacheHit( storageEntry ); + qDebug() << "cachehit:" << fullUrl << ":" << storageEntry->getFilePath(); + + if ( storageEntry.isNull() ) { + return QSharedPointer<TempFile>( nullptr ); + } + + QFile cacheHit( storageEntry->getFilePath() ); + + if ( cacheHit.exists() ) { + return storageEntry; + } - if ( cacheHit.exists() ) { - return QSharedPointer<TempFile>::create( storageEntry, pRequest->url ); + mStorage->removeFileCacheEntry( pRequest->url, storageEntry->getFilePath() ); + repo->remove( fullUrl ); } - mStorage->removeFileCacheEntry( pRequest->url, storageEntry ); return QSharedPointer<TempFile>( nullptr ); @@ -218,6 +242,8 @@ void FileService::getFileFromServer( const QSharedPointer< FileRequest > &pReque if ( location.size() ) { if ( pRequest->showInline ) { mStorage->addFileCacheEntry( url, location ); + auto repo = mServer->getFiles(); + repo->add( url, tempfile ); } mCurrentDownloads.remove( fullUrl ); @@ -239,6 +265,8 @@ void FileService::getFileFromServer( const QSharedPointer< FileRequest > &pReque if ( pRequest->showInline ) { mStorage->addFileCacheEntry( url, location ); + auto repo = mServer->getFiles(); + repo->add( url, tempfile ); } pRequest->then( tempfile, pRequest->showInline ); diff --git a/services/fileservice.h b/services/fileservice.h index 96c45405951a86afa03bf7659424b9c49e6c66d5..09b4eda46bb7eb1e9c6792694ba486cf255c6b37 100644 --- a/services/fileservice.h +++ b/services/fileservice.h @@ -28,7 +28,9 @@ #include <QMimeDatabase> #include "repos/entities/tempfile.h" #include "rocketchatserver.h" +#include "persistancelayer.h" class RocketChatServerData; +class PersistanceLayer; class FileRequest { @@ -45,6 +47,7 @@ class FileService public: explicit FileService( RocketChatServerData *server ); bool getFileRessource( const QSharedPointer< FileRequest > &pRequest ); + void getFilesFromDb(); protected: QMutex mDownloadMutex; QSharedPointer<TempFile> getFileFromCache( const QSharedPointer< FileRequest > &pRequest ); diff --git a/services/messageservice.cpp b/services/messageservice.cpp index f39a15e5e0e02f6e26182db2ae75fe73755bf22c..fb68c56c0e962940c29d135ccc0ebedc7be4ab99 100644 --- a/services/messageservice.cpp +++ b/services/messageservice.cpp @@ -22,8 +22,8 @@ #include <algorithm> #include "messageservice.h" -#include <repos/entities/rocketchatreplymessage.h> - +#include "repos/entities/rocketchatreplymessage.h" +#include "services/fileservice.h" //MessageService::MessageService( PersistanceLayer *pPersistanceLayer, @@ -36,8 +36,9 @@ MessageService::MessageService( QObject *parent, PersistanceLayer *pPersistanceLayer, RocketChatServerData *pServer, - EmojiRepo *pEmojiRepo ): QObject( parent ), mReplyRegeEx( "\\[ \\]\\(.*\\)</a>" ), mEmojiRepo( pEmojiRepo ), mMessagesModel( Models::getMessagesModel() ), - mReplyReplyRegeEx( "\\[ \\]\\(.*\\)" ), mSearchResults( Models::getMessagesSearchModel() ) + EmojiRepo *pEmojiRepo, FileService *pFileService ): QObject( parent ), + mReplyRegeEx( "\\[ \\]\\(.*\\)</a>" ), mEmojiRepo( pEmojiRepo ), mMessagesModel( Models::getMessagesModel() ), + mReplyReplyRegeEx( "\\[ \\]\\(.*\\)" ), mSearchResults( Models::getMessagesSearchModel() ), mFileService( pFileService ) { this->mPersistanceLayer = pPersistanceLayer; this->mServer = pServer; @@ -106,6 +107,26 @@ void MessageService::persistMessages( const MessageList &pMessage ) mPersistanceLayer->askForcommit(); } +void MessageService::persist() +{ + mPersistanceLayer->transaction(); + auto channels = mServer->getChannels(); + + for ( const auto &channel : channels->getElements() ) { + if ( channel.isNull() ) { + auto messages = channel->getMessageRepo(); + + for ( const auto &message : messages->getElements() ) { + if ( !message.isNull() ) { + persistMessage( message ); + } + } + } + } + + mPersistanceLayer->askForcommit(); +} + QSharedPointer<RocketChatMessage> MessageService::parseMessage( const QJsonObject &pMessageData, bool linkify ) { @@ -190,6 +211,14 @@ QSharedPointer<RocketChatMessage> MessageService::parseMessage( const QJsonObjec } } + //TODO: place RocketChatUserObject inside Message instead... + auto then = [ message ]( QSharedPointer<TempFile> tempfile, bool showInline ) { + message->setAvatarImg( tempfile ); + }; + auto avatarUrl = "/avatar/" + author + ".jpg"; + auto avatarRequest = QSharedPointer<FileRequest>::create( avatarUrl, "temp", then, true ); + mFileService->getFileRessource( avatarRequest ); + message->setAuthor( author ); message->setFormattedDate( formattedDate ); message->setFormattedTime( formattedTime ); diff --git a/services/messageservice.h b/services/messageservice.h index b766ab1998264087f5f24283801ea5c545ee9f91..f4c00a275e4afb73b22c2f22bbb89e13f44a8e37 100644 --- a/services/messageservice.h +++ b/services/messageservice.h @@ -40,23 +40,26 @@ #include "services/requests/loadmissedmessageservicerequest.h" #include "CustomModels/messagemodel.h" #include "CustomModels/messagesearchresultsmodel.h" +#include "services/fileservice.h" typedef QList<QSharedPointer<RocketChatMessage>> MessageList; typedef QSharedPointer<RocketChatMessage> ChatMessage; class PersistanceLayer; class RocketChatServerData; +class FileService; class MessageService : public QObject { Q_OBJECT public: - // MessageService(PersistanceLayer *pPersistanceLayer, RocketChatServerData* pServer, const QHash<QString, QString> &pEmojisMap); - MessageService( QObject *parent, PersistanceLayer *pPersistanceLayer, RocketChatServerData *pServer, EmojiRepo *mEmojiRepo ); + // MessageService(PersistanceLayer *pPersistanceLayer, RocketChatServerData* pServer, const QHash<QString, QString> &pEmojisMap, FileService &pFileService); + MessageService( QObject *parent, PersistanceLayer *pPersistanceLayer, RocketChatServerData *pServer, EmojiRepo *mEmojiRepo, FileService *pFileService ); void loadHistory( const QSharedPointer<LoadHistoryServiceRequest> & ); void checkForMissingMessages( const QSharedPointer<LoadMissedMessageServiceRequest> &pRequest ); void sendMessage( const QSharedPointer<RocketChatMessage> &pMessage ); void persistMessage( const QSharedPointer<RocketChatMessage> &pMessage ); void persistMessages( const MessageList &pMessage ); + void persist(); QSharedPointer<RocketChatMessage> parseMessage( const QJsonObject &pMessage, bool linkify = true ); void addUserToBlockList( const QString &pId ); void addChannelToBlockList( const QString &pId ); @@ -70,6 +73,7 @@ class MessageService : public QObject PersistanceLayer *mPersistanceLayer; RocketChatServerData *mServer; MessageSearchResultsModel *mSearchResults; + FileService *mFileService; void loadHistoryFromServer( const QSharedPointer<LoadHistoryRequestContainer> &pContainer ); void loadHistoryFromServer( const QSharedPointer<LoadHistoryServiceRequest> &pContainer ); diff --git a/services/rocketchatchannelservice.cpp b/services/rocketchatchannelservice.cpp index 159575f0f5576b43ffa9e73f4e52bcfed31d9026..88d5ebcf57f475a336b09b54a19af7c54ca0d75d 100755 --- a/services/rocketchatchannelservice.cpp +++ b/services/rocketchatchannelservice.cpp @@ -26,7 +26,7 @@ -RocketChatChannelService::RocketChatChannelService( QObject *parent, RocketChatServerData *pServer, MessageService *pMessageService ): QObject( parent ) +RocketChatChannelService::RocketChatChannelService( QObject *parent, RocketChatServerData *pServer, MessageService *pMessageService, FileService *pFileService ): QObject( parent ), mFileService( pFileService ) { this->mServer = pServer; this->mMessageService = pMessageService; @@ -54,7 +54,18 @@ QSharedPointer<RocketChatChannel> RocketChatChannelService::createChannelObject( QSharedPointer<RocketChatChannel> RocketChatChannelService::createChannelObject( const QString &pRoomId, const QString &pName, const QString &pType, const QString &pUsername ) { auto ptr = QSharedPointer<RocketChatChannel>::create( mServer, mMessageService, pRoomId, pName, pType ); - ptr->setUsername( pUsername ); + + if ( pType == "d" ) { + ptr->setUsername( pUsername ); + + //TODO: place RocketChatUserObject inside Message instead... + auto then = [ ptr ]( QSharedPointer<TempFile> tempfile, bool showInline ) { + ptr->setAvatarImg( tempfile ); + }; + auto avatarUrl = "/avatar/" + pUsername + ".jpg"; + auto avatarRequest = QSharedPointer<FileRequest>::create( avatarUrl, "temp", then, true ); + mFileService->getFileRessource( avatarRequest ); + } if ( Q_LIKELY( mChannels ) ) { mChannels->add( ptr ); @@ -182,7 +193,7 @@ QVector<QSharedPointer<RocketChatChannel> > RocketChatChannelService::processCha vec.append( channel ); - persistChannel( channel ); + //persistChannel( channel ); } } @@ -305,6 +316,17 @@ void RocketChatChannelService::persistChannel( const QSharedPointer<RocketChatCh auto chatPartnerId = pChannel->getChatPartnerId(); mStorage->addChannel( id, name, type, joined, readonly, muted, archived, blocked, username, chatPartnerId ); } + +void RocketChatChannelService::persist() +{ + mStorage->transaction(); + + for ( const auto &channel : mChannels->getElements() ) { + persistChannel( channel ); + } + + mStorage->askForcommit(); +} /** * Fills the channel with users, which are loaded from the server * diff --git a/services/rocketchatchannelservice.h b/services/rocketchatchannelservice.h index 6944a95e4f927b698a25481b7293f33ba04cf939..af2508da5734b5b16068f1d6c99080e6c2089790 100755 --- a/services/rocketchatchannelservice.h +++ b/services/rocketchatchannelservice.h @@ -40,6 +40,7 @@ #include "restRequests/restspotlightrequest.h" #include "services/messageservice.h" #include "repos/channelrepository.h" +#include "fileservice.h" #include "CustomModels/models.h" @@ -55,7 +56,7 @@ class RocketChatChannelService : public QObject { Q_OBJECT public: - RocketChatChannelService( QObject *parent, RocketChatServerData *pServer, MessageService *pMessageService ); + RocketChatChannelService( QObject *parent, RocketChatServerData *pServer, MessageService *pMessageService, FileService *pFileService ); RestApi *getRestApi() const; void setRestApi( RestApi *pValue ); @@ -71,6 +72,7 @@ class RocketChatChannelService : public QObject void loadJoinedChannelsFromServer( void ); void loadJoinedChannelsFromDb( void ); void persistChannel( const QSharedPointer<RocketChatChannel> &pChannel ); + void persist(); void loadUsersOfChannel( const QSharedPointer<RocketChatChannel> &pChannel ); void subscribeChannel( const QSharedPointer<RocketChatChannel> &pChannel ); void subscribeChannel( const QString &pChannel ); @@ -101,6 +103,7 @@ class RocketChatChannelService : public QObject PersistanceLayer *mStorage = nullptr; RocketChatServerData *mServer = nullptr; ChannelRepository *mChannels = nullptr; + FileService *mFileService = nullptr; MeteorDDP *mDdp; QVector<QSharedPointer<RocketChatChannel>> processChannelData( const QJsonArray &pChannelArray, bool pJoined, bool pUpdateOnly );