summary refs log tree commit diff
diff options
context:
space:
mode:
authorKonstantinos Sideris <sideris.konstantin@gmail.com>2018-01-21 21:43:21 +0200
committerKonstantinos Sideris <sideris.konstantin@gmail.com>2018-01-21 21:43:21 +0200
commitc59cd0e80bcbf1e37b7d6b021275d4c8f90f1914 (patch)
treee809690d042aca74c620b09f4a9f471cbe2240a3
parentRefactor avatar fetching in one function (diff)
downloadnheko-c59cd0e80bcbf1e37b7d6b021275d4c8f90f1914.tar.xz
Load the initial cache data without blocking the UI
-rw-r--r--CMakeLists.txt1
-rw-r--r--include/Cache.h14
-rw-r--r--include/RoomState.h2
-rw-r--r--src/Cache.cc9
-rw-r--r--src/ChatPage.cc63
5 files changed, 52 insertions, 37 deletions
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 <QDir>
+#include <QMap>
 #include <json.hpp>
 #include <lmdb++.h>
 #include <mtx/responses.hpp>
 
-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<std::string>();
 }
 
-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<QString, QSharedPointer<RoomState>> &states);
         bool isInitialized() const;
 
         QString nextBatchToken() const;
-        QMap<QString, RoomState> states();
+        void states();
 
         using Invites = std::map<std::string, mtx::responses::InvitedRoom>;
         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<QString, RoomState> 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<class Collection>
 void
 RoomState::updateFromEvents(const std::vector<Collection> &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<uint64_t, std::string, std::greater<uint64_t>>;
 using Receipts       = std::map<std::string, std::map<std::string, uint64_t>>;
 
-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<QString, RoomState>
+void
 Cache::states()
 {
         QMap<QString, RoomState> 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<QMap<QString, RoomState>>();
 
-        for (auto it = rooms.constBegin(); it != rooms.constEnd(); ++it) {
-                auto roomState = QSharedPointer<RoomState>(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<QString, RoomState> 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<RoomState>(new RoomState(it.value()));
 
-                // Create or restore the settings for this room.
-                roomSettings_.insert(it.key(),
-                                     QSharedPointer<RoomSettings>(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<RoomSettings>(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