diff --git a/CMakeLists.txt b/CMakeLists.txt index b8450a98..9091a0b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -277,6 +277,7 @@ qt5_wrap_cpp(MOC_HEADERS include/ui/ThemeManager.h include/AvatarProvider.h + include/Cache.h include/ChatPage.h include/CommunitiesListItem.h include/CommunitiesList.h diff --git a/include/Cache.h b/include/Cache.h index 7a626e12..e8d797dd 100644 --- a/include/Cache.h +++ b/include/Cache.h @@ -18,11 +18,12 @@ #pragma once #include +#include #include #include #include -class RoomState; +#include "RoomState.h" //! Used to uniquely identify a list of read receipts. struct ReadReceiptKey @@ -44,17 +45,19 @@ from_json(const json &j, ReadReceiptKey &key) key.room_id = j.at("room_id").get(); } -class Cache +class Cache : public QObject { + Q_OBJECT + public: - Cache(const QString &userId); + Cache(const QString &userId, QObject *parent = nullptr); void setState(const QString &nextBatchToken, const QMap> &states); bool isInitialized() const; QString nextBatchToken() const; - QMap states(); + void states(); using Invites = std::map; Invites invites(); @@ -86,6 +89,9 @@ public: QByteArray image(const QString &url) const; void saveImage(const QString &url, const QByteArray &data); +signals: + void statesLoaded(QMap states); + private: void setNextBatchToken(lmdb::txn &txn, const QString &token); void insertRoomState(lmdb::txn &txn, diff --git a/include/RoomState.h b/include/RoomState.h index 0e91410c..6f335263 100644 --- a/include/RoomState.h +++ b/include/RoomState.h @@ -77,6 +77,8 @@ private: QString userAvatar_; }; +Q_DECLARE_METATYPE(RoomState) + template void RoomState::updateFromEvents(const std::vector &collection) diff --git a/src/Cache.cc b/src/Cache.cc index fd6a5ee9..32176369 100644 --- a/src/Cache.cc +++ b/src/Cache.cc @@ -33,8 +33,9 @@ static const lmdb::val CACHE_FORMAT_VERSION_KEY("cache_format_version"); using CachedReceipts = std::multimap>; using Receipts = std::map>; -Cache::Cache(const QString &userId) - : env_{nullptr} +Cache::Cache(const QString &userId, QObject *parent) + : QObject{parent} + , env_{nullptr} , stateDb_{0} , roomDb_{0} , invitesDb_{0} @@ -248,7 +249,7 @@ Cache::removeInvite(const QString &room_id) txn.commit(); } -QMap +void Cache::states() { QMap states; @@ -301,7 +302,7 @@ Cache::states() txn.commit(); - return states; + emit statesLoaded(states); } void diff --git a/src/ChatPage.cc b/src/ChatPage.cc index 596f72dc..225434e6 100644 --- a/src/ChatPage.cc +++ b/src/ChatPage.cc @@ -648,46 +648,51 @@ ChatPage::loadStateFromCache() qDebug() << "Restored nextBatchToken" << cache_->nextBatchToken(); client_->setNextBatchToken(cache_->nextBatchToken()); - // Fetch all the joined room's state. - auto rooms = cache_->states(); + qRegisterMetaType>(); - for (auto it = rooms.constBegin(); it != rooms.constEnd(); ++it) { - auto roomState = QSharedPointer(new RoomState(it.value())); + QtConcurrent::run(cache_.data(), &Cache::states); - // Clean up and prepare state for use. - roomState->removeLeaveMemberships(); - roomState->resolveName(); - roomState->resolveAvatar(); + connect(cache_.data(), &Cache::statesLoaded, this, [this](QMap rooms) { + qDebug() << "Cache data loaded"; - // Save the current room state. - roomStates_.insert(it.key(), roomState); + for (auto it = rooms.constBegin(); it != rooms.constEnd(); ++it) { + auto roomState = QSharedPointer(new RoomState(it.value())); - // Create or restore the settings for this room. - roomSettings_.insert(it.key(), - QSharedPointer(new RoomSettings(it.key()))); + // Clean up and prepare state for use. + roomState->removeLeaveMemberships(); + roomState->resolveName(); + roomState->resolveAvatar(); - // Resolve user avatars. - for (const auto membership : roomState->memberships) { - updateUserDisplayName(membership.second); - updateUserAvatarUrl(membership.second); + // Save the current room state. + roomStates_.insert(it.key(), roomState); + + // Create or restore the settings for this room. + roomSettings_.insert( + it.key(), QSharedPointer(new RoomSettings(it.key()))); + + // Resolve user avatars. + for (const auto membership : roomState->memberships) { + updateUserDisplayName(membership.second); + updateUserAvatarUrl(membership.second); + } } - } - // Initializing empty timelines. - view_manager_->initialize(rooms.keys()); + // Initializing empty timelines. + view_manager_->initialize(rooms.keys()); - // Initialize room list from the restored state and settings. - room_list_->setInitialRooms(roomSettings_, roomStates_); - room_list_->syncInvites(cache_->invites()); + // Initialize room list from the restored state and settings. + room_list_->setInitialRooms(roomSettings_, roomStates_); + room_list_->syncInvites(cache_->invites()); - // Check periodically if the timelines have been loaded. - consensusTimer_->start(CONSENSUS_TIMEOUT); + // Check periodically if the timelines have been loaded. + consensusTimer_->start(CONSENSUS_TIMEOUT); - // Show the content if consensus can't be achieved. - showContentTimer_->start(SHOW_CONTENT_TIMEOUT); + // Show the content if consensus can't be achieved. + showContentTimer_->start(SHOW_CONTENT_TIMEOUT); - // Start receiving events. - client_->sync(); + // Start receiving events. + client_->sync(); + }); } void