diff --git a/include/AvatarProvider.h b/include/AvatarProvider.h index af13a577..ce82f2aa 100644 --- a/include/AvatarProvider.h +++ b/include/AvatarProvider.h @@ -17,27 +17,18 @@ #pragma once -#include #include -#include #include -class TimelineItem; -class Cache; - class AvatarProvider : public QObject { Q_OBJECT public: - static void init(QSharedPointer cache) { cache_ = cache; } //! The callback is called with the downloaded avatar for the given user //! or the avatar is downloaded first and then saved for re-use. static void resolve(const QString &room_id, const QString &userId, QObject *receiver, std::function callback); - -private: - static QSharedPointer cache_; }; diff --git a/include/Cache.h b/include/Cache.h index 7ecc5d59..c038b3d9 100644 --- a/include/Cache.h +++ b/include/Cache.h @@ -435,3 +435,11 @@ private: QString localUserId_; QString cacheDirectory_; }; + +namespace cache { +void +init(const QString &userId, QObject *parent); + +Cache * +client(); +} diff --git a/include/ChatPage.h b/include/ChatPage.h index 057ce698..799f7a2e 100644 --- a/include/ChatPage.h +++ b/include/ChatPage.h @@ -69,7 +69,6 @@ public: static ChatPage *instance() { return instance_; } QSharedPointer userSettings() { return userSettings_; } - QSharedPointer cache() { return cache_; } void deleteConfigs(); signals: @@ -183,9 +182,6 @@ private: // Global user settings. QSharedPointer userSettings_; - - // LMDB wrapper. - QSharedPointer cache_; }; template diff --git a/include/QuickSwitcher.h b/include/QuickSwitcher.h index ce3c4f25..254d7a16 100644 --- a/include/QuickSwitcher.h +++ b/include/QuickSwitcher.h @@ -22,7 +22,6 @@ #include #include -#include "Cache.h" #include "SuggestionsPopup.hpp" #include "TextField.h" @@ -50,7 +49,7 @@ class QuickSwitcher : public QWidget Q_OBJECT public: - QuickSwitcher(QSharedPointer cache, QWidget *parent = nullptr); + QuickSwitcher(QWidget *parent = nullptr); signals: void closing(); @@ -77,6 +76,4 @@ private: //! Autocomplete popup box with the room suggestions. SuggestionsPopup popup_; - //! Cache client for room quering. - QSharedPointer cache_; }; diff --git a/include/RoomList.h b/include/RoomList.h index 202e075c..98d9443e 100644 --- a/include/RoomList.h +++ b/include/RoomList.h @@ -30,7 +30,6 @@ class OverlayModal; class RoomInfoListItem; class Sync; class UserSettings; -class Cache; struct DescInfo; struct RoomInfo; @@ -41,7 +40,6 @@ class RoomList : public QWidget public: RoomList(QSharedPointer userSettings, QWidget *parent = 0); - void setCache(QSharedPointer cache) { cache_ = cache; } void initialize(const QMap &info); void sync(const std::map &info); @@ -102,7 +100,6 @@ private: //! Which rooms to include in the room list. std::vector roomFilter_; - QSharedPointer cache_; QSharedPointer userSettings_; bool isSortPending_ = false; diff --git a/include/TextInputWidget.h b/include/TextInputWidget.h index 1f122504..c679b9b2 100644 --- a/include/TextInputWidget.h +++ b/include/TextInputWidget.h @@ -36,8 +36,6 @@ #include "emoji/PickButton.h" -class Cache; - namespace dialogs { class PreviewUploadOverlay; } @@ -131,7 +129,6 @@ public: QColor borderColor() const { return borderColor_; } void setBorderColor(QColor &color) { borderColor_ = color; } - void setCache(QSharedPointer cache) { cache_ = cache; } public slots: void openFileSelection(); @@ -172,7 +169,5 @@ private: FlatButton *sendMessageBtn_; emoji::PickButton *emojiBtn_; - QSharedPointer cache_; - QColor borderColor_; }; diff --git a/include/dialogs/MemberList.hpp b/include/dialogs/MemberList.hpp index bdc11486..9c3dc5dc 100644 --- a/include/dialogs/MemberList.hpp +++ b/include/dialogs/MemberList.hpp @@ -4,7 +4,6 @@ #include class Avatar; -class Cache; class FlatButton; class QHBoxLayout; class QLabel; @@ -38,7 +37,7 @@ class MemberList : public QFrame { Q_OBJECT public: - MemberList(const QString &room_id, QSharedPointer cache, QWidget *parent = nullptr); + MemberList(const QString &room_id, QWidget *parent = nullptr); public slots: void addUsers(const std::vector &users); @@ -57,7 +56,6 @@ private: QString room_id_; QLabel *topLabel_; QListWidget *list_; - QSharedPointer cache_; FlatButton *moreBtn_; }; } // dialogs diff --git a/include/dialogs/RoomSettings.hpp b/include/dialogs/RoomSettings.hpp index fbbc2e02..2acbf4b1 100644 --- a/include/dialogs/RoomSettings.hpp +++ b/include/dialogs/RoomSettings.hpp @@ -59,9 +59,7 @@ class RoomSettings : public QFrame { Q_OBJECT public: - RoomSettings(const QString &room_id, - QSharedPointer cache, - QWidget *parent = nullptr); + RoomSettings(const QString &room_id, QWidget *parent = nullptr); signals: void closing(); @@ -74,8 +72,6 @@ private: void setAvatar(const QImage &img) { avatarImg_ = img; } - QSharedPointer cache_; - // Button section FlatButton *saveBtn_; FlatButton *cancelBtn_; diff --git a/src/AvatarProvider.cc b/src/AvatarProvider.cc index 51ff27ac..49e52a82 100644 --- a/src/AvatarProvider.cc +++ b/src/AvatarProvider.cc @@ -22,8 +22,6 @@ #include "Cache.h" #include "MatrixClient.h" -QSharedPointer AvatarProvider::cache_; - void AvatarProvider::resolve(const QString &room_id, const QString &user_id, @@ -33,13 +31,13 @@ AvatarProvider::resolve(const QString &room_id, const auto key = QString("%1 %2").arg(room_id).arg(user_id); const auto avatarUrl = Cache::avatarUrl(room_id, user_id); - if (!Cache::AvatarUrls.contains(key) || cache_.isNull()) + if (!Cache::AvatarUrls.contains(key) || !cache::client()) return; if (avatarUrl.isEmpty()) return; - auto data = cache_->image(avatarUrl); + auto data = cache::client()->image(avatarUrl); if (!data.isNull()) { callback(QImage::fromData(data)); return; @@ -61,7 +59,7 @@ AvatarProvider::resolve(const QString &room_id, buffer.open(QIODevice::WriteOnly); img.save(&buffer, "PNG"); - cache_->saveImage(avatarUrl, data); + cache::client()->saveImage(avatarUrl, data); }); callback(img); }); diff --git a/src/Cache.cc b/src/Cache.cc index 8964c0e0..d80834aa 100644 --- a/src/Cache.cc +++ b/src/Cache.cc @@ -53,6 +53,25 @@ static constexpr const char *NOTIFICATIONS_DB = "sent_notifications"; using CachedReceipts = std::multimap>; using Receipts = std::map>; +namespace { +Cache *instance_ = nullptr; +} + +namespace cache { +void +init(const QString &user_id, QObject *parent) +{ + if (!instance_) + instance_ = new Cache(user_id, parent); +} + +Cache * +client() +{ + return instance_; +} +} + Cache::Cache(const QString &userId, QObject *parent) : QObject{parent} , env_{nullptr} diff --git a/src/ChatPage.cc b/src/ChatPage.cc index 649d783c..7f08eda6 100644 --- a/src/ChatPage.cc +++ b/src/ChatPage.cc @@ -323,7 +323,7 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) // We remove any invites with the same room_id. try { - cache_->removeInvite(room_id.toStdString()); + cache::client()->removeInvite(room_id.toStdString()); } catch (const lmdb::error &e) { emit showNotification(QString("Failed to remove invite: %1") .arg(QString::fromStdString(e.what()))); @@ -416,7 +416,7 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) [this](const std::vector &rooms) { view_manager_->initialize(rooms); }); connect(this, &ChatPage::syncUI, this, [this](const mtx::responses::Rooms &rooms) { try { - room_list_->cleanupInvites(cache_->invites()); + room_list_->cleanupInvites(cache::client()->invites()); } catch (const lmdb::error &e) { qWarning() << "failed to retrieve invites" << e.what(); } @@ -484,7 +484,7 @@ ChatPage::deleteConfigs() settings.remove(""); settings.endGroup(); - cache_->deleteData(); + cache::client()->deleteData(); http::client()->reset(); } @@ -497,28 +497,24 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token) http::client()->getOwnProfile(); http::client()->getOwnCommunities(); - cache_ = QSharedPointer(new Cache(userid)); - room_list_->setCache(cache_); - text_input_->setCache(cache_); - - AvatarProvider::init(cache_); + cache::init(userid, this); try { - cache_->setup(); + cache::client()->setup(); - if (!cache_->isFormatValid()) { - cache_->deleteData(); - cache_->setup(); - cache_->setCurrentFormat(); + if (!cache::client()->isFormatValid()) { + cache::client()->deleteData(); + cache::client()->setup(); + cache::client()->setCurrentFormat(); } - if (cache_->isInitialized()) { + if (cache::client()->isInitialized()) { loadStateFromCache(); return; } } catch (const lmdb::error &e) { qCritical() << "Cache failure" << e.what(); - cache_->deleteData(); + cache::client()->deleteData(); qInfo() << "Falling back to initial sync ..."; } @@ -534,16 +530,16 @@ ChatPage::syncCompleted(const mtx::responses::Sync &response) QtConcurrent::run([this, res = std::move(response)]() { try { - cache_->saveState(res); + cache::client()->saveState(res); emit syncUI(res.rooms); - emit syncRoomlist(cache_->roomUpdates(res)); + emit syncRoomlist(cache::client()->roomUpdates(res)); } catch (const lmdb::error &e) { std::cout << "save cache error:" << e.what() << '\n'; // TODO: retry sync. return; } - emit continueSync(cache_->nextBatchToken()); + emit continueSync(cache::client()->nextBatchToken()); }); } @@ -556,16 +552,16 @@ ChatPage::initialSyncCompleted(const mtx::responses::Sync &response) QtConcurrent::run([this, res = std::move(response)]() { try { - cache_->saveState(res); + cache::client()->saveState(res); emit initializeViews(std::move(res.rooms)); - emit initializeRoomList(cache_->roomInfo()); + emit initializeRoomList(cache::client()->roomInfo()); } catch (const lmdb::error &e) { qWarning() << "cache error:" << QString::fromStdString(e.what()); emit retryInitialSync(); return; } - emit continueSync(cache_->nextBatchToken()); + emit continueSync(cache::client()->nextBatchToken()); emit contentLoaded(); }); } @@ -591,8 +587,8 @@ ChatPage::updateOwnProfileInfo(const QUrl &avatar_url, const QString &display_na if (!avatar_url.isValid()) return; - if (!cache_.isNull()) { - auto data = cache_->image(avatar_url.toString()); + if (cache::client()) { + auto data = cache::client()->image(avatar_url.toString()); if (!data.isNull()) { user_info_widget_->setAvatar(QImage::fromData(data)); return; @@ -635,7 +631,7 @@ ChatPage::changeTopRoomInfo(const QString &room_id) } try { - auto room_info = cache_->getRoomInfo({room_id.toStdString()}); + auto room_info = cache::client()->getRoomInfo({room_id.toStdString()}); if (room_info.find(room_id) == room_info.end()) return; @@ -646,7 +642,7 @@ ChatPage::changeTopRoomInfo(const QString &room_id) top_bar_->updateRoomName(name); top_bar_->updateRoomTopic(QString::fromStdString(room_info[room_id].topic)); - auto img = cache_->getRoomAvatar(room_id); + auto img = cache::client()->getRoomAvatar(room_id); if (img.isNull()) top_bar_->updateRoomAvatarFromName(name); @@ -679,10 +675,10 @@ ChatPage::loadStateFromCache() QtConcurrent::run([this]() { try { - cache_->populateMembers(); + cache::client()->populateMembers(); - emit initializeEmptyViews(cache_->joinedRooms()); - emit initializeRoomList(cache_->roomInfo()); + emit initializeEmptyViews(cache::client()->joinedRooms()); + emit initializeRoomList(cache::client()->roomInfo()); } catch (const lmdb::error &e) { std::cout << "load cache error:" << e.what() << '\n'; // TODO Clear cache and restart. @@ -690,7 +686,7 @@ ChatPage::loadStateFromCache() } // Start receiving events. - emit continueSync(cache_->nextBatchToken()); + emit continueSync(cache::client()->nextBatchToken()); // Check periodically if the timelines have been loaded. emit startConsesusTimer(); @@ -702,7 +698,7 @@ ChatPage::showQuickSwitcher() { if (quickSwitcher_.isNull()) { quickSwitcher_ = QSharedPointer( - new QuickSwitcher(cache_, this), + new QuickSwitcher(this), [](QuickSwitcher *switcher) { switcher->deleteLater(); }); connect(quickSwitcher_.data(), @@ -731,8 +727,8 @@ void ChatPage::removeRoom(const QString &room_id) { try { - cache_->removeRoom(room_id); - cache_->removeInvite(room_id.toStdString()); + cache::client()->removeRoom(room_id); + cache::client()->removeInvite(room_id.toStdString()); } catch (const lmdb::error &e) { qCritical() << "The cache couldn't be updated: " << e.what(); // TODO: Notify the user. @@ -800,7 +796,7 @@ ChatPage::showReadReceipts(const QString &event_id) receiptsModal_->setColor(QColor(30, 30, 30, 170)); } - receiptsDialog_->addUsers(cache_->readReceipts(event_id, current_room_)); + receiptsDialog_->addUsers(cache::client()->readReceipts(event_id, current_room_)); receiptsModal_->show(); } @@ -858,23 +854,24 @@ ChatPage::sendDesktopNotifications(const mtx::responses::Notifications &res) try { if (item.read) { - cache_->removeReadNotification(event_id); + cache::client()->removeReadNotification(event_id); continue; } - if (!cache_->isNotificationSent(event_id)) { + if (!cache::client()->isNotificationSent(event_id)) { const auto room_id = QString::fromStdString(item.room_id); const auto user_id = utils::event_sender(item.event); // We should only sent one notification per event. - cache_->markSentNotification(event_id); + cache::client()->markSentNotification(event_id); // Don't send a notification when the current room is opened. if (isRoomActive(room_id)) continue; NotificationsManager::postNotification( - QString::fromStdString(cache_->singleRoomInfo(item.room_id).name), + QString::fromStdString( + cache::client()->singleRoomInfo(item.room_id).name), Cache::displayName(room_id, user_id), utils::event_body(item.event)); } diff --git a/src/MainWindow.cc b/src/MainWindow.cc index b0a0af4a..745fb210 100644 --- a/src/MainWindow.cc +++ b/src/MainWindow.cc @@ -276,8 +276,8 @@ MainWindow::openRoomSettings(const QString &room_id) { const auto roomToSearch = room_id.isEmpty() ? chat_page_->currentRoom() : ""; - roomSettingsDialog_ = QSharedPointer( - new dialogs::RoomSettings(roomToSearch, chat_page_->cache(), this)); + roomSettingsDialog_ = + QSharedPointer(new dialogs::RoomSettings(roomToSearch, this)); connect(roomSettingsDialog_.data(), &dialogs::RoomSettings::closing, this, [this]() { roomSettingsModal_->hide(); @@ -294,8 +294,8 @@ MainWindow::openMemberListDialog(const QString &room_id) { const auto roomToSearch = room_id.isEmpty() ? chat_page_->currentRoom() : ""; - memberListDialog_ = QSharedPointer( - new dialogs::MemberList(roomToSearch, chat_page_->cache(), this)); + memberListDialog_ = + QSharedPointer(new dialogs::MemberList(roomToSearch, this)); memberListModal_ = QSharedPointer(new OverlayModal(this, memberListDialog_.data())); diff --git a/src/QuickSwitcher.cc b/src/QuickSwitcher.cc index 2aa05f3c..3c9725d1 100644 --- a/src/QuickSwitcher.cc +++ b/src/QuickSwitcher.cc @@ -56,9 +56,8 @@ RoomSearchInput::hideEvent(QHideEvent *event) TextField::hideEvent(event); } -QuickSwitcher::QuickSwitcher(QSharedPointer cache, QWidget *parent) +QuickSwitcher::QuickSwitcher(QWidget *parent) : QWidget(parent) - , cache_{cache} { qRegisterMetaType>(); setMaximumWidth(450); @@ -93,7 +92,8 @@ QuickSwitcher::QuickSwitcher(QSharedPointer cache, QWidget *parent) QtConcurrent::run([this, query = query.toLower()]() { try { - emit queryResults(cache_->searchRooms(query.toStdString())); + emit queryResults( + cache::client()->searchRooms(query.toStdString())); } catch (const lmdb::error &e) { qWarning() << "room search failed:" << e.what(); } diff --git a/src/RoomList.cc b/src/RoomList.cc index 12fec318..e7c5ef30 100644 --- a/src/RoomList.cc +++ b/src/RoomList.cc @@ -62,8 +62,8 @@ RoomList::RoomList(QSharedPointer userSettings, QWidget *parent) const QPixmap &img, const QString &url, const QByteArray &data) { - if (!cache_.isNull()) - cache_->saveImage(url, data); + if (cache::client()) + cache::client()->saveImage(url, data); updateRoomAvatar(room_id, img); }); @@ -97,8 +97,8 @@ RoomList::updateAvatar(const QString &room_id, const QString &url) QByteArray savedImgData; - if (!cache_.isNull()) - savedImgData = cache_->image(url); + if (cache::client()) + savedImgData = cache::client()->image(url); if (savedImgData.isEmpty()) { http::client()->fetchRoomAvatar(room_id, url); diff --git a/src/TextInputWidget.cc b/src/TextInputWidget.cc index beae9aab..f3753971 100644 --- a/src/TextInputWidget.cc +++ b/src/TextInputWidget.cc @@ -453,12 +453,12 @@ TextInputWidget::TextInputWidget(QWidget *parent) input_->setFixedHeight(textInputHeight); }); connect(input_, &FilteredTextEdit::showSuggestions, this, [this](const QString &q) { - if (q.isEmpty() || cache_.isNull()) + if (q.isEmpty() || !cache::client()) return; QtConcurrent::run([this, q = q.toLower().toStdString()]() { try { - emit input_->resultsRetrieved(cache_->searchUsers( + emit input_->resultsRetrieved(cache::client()->searchUsers( ChatPage::instance()->currentRoom().toStdString(), q)); } catch (const lmdb::error &e) { std::cout << e.what() << '\n'; diff --git a/src/dialogs/MemberList.cpp b/src/dialogs/MemberList.cpp index 2d435026..f0f61686 100644 --- a/src/dialogs/MemberList.cpp +++ b/src/dialogs/MemberList.cpp @@ -56,10 +56,9 @@ MemberItem::MemberItem(const RoomMember &member, QWidget *parent) topLayout_->addLayout(textLayout_, 1); } -MemberList::MemberList(const QString &room_id, QSharedPointer cache, QWidget *parent) +MemberList::MemberList(const QString &room_id, QWidget *parent) : QFrame(parent) , room_id_{room_id} - , cache_{cache} { setMaximumSize(420, 380); setAttribute(Qt::WA_DeleteOnClose, true); @@ -99,11 +98,11 @@ MemberList::MemberList(const QString &room_id, QSharedPointer cache, QWid const size_t numMembers = list_->count() - 1; if (numMembers > 0) - addUsers(cache_->getMembers(room_id_.toStdString(), numMembers)); + addUsers(cache::client()->getMembers(room_id_.toStdString(), numMembers)); }); try { - addUsers(cache_->getMembers(room_id_.toStdString())); + addUsers(cache::client()->getMembers(room_id_.toStdString())); } catch (const lmdb::error &e) { qCritical() << e.what(); } diff --git a/src/dialogs/RoomSettings.cpp b/src/dialogs/RoomSettings.cpp index b2c87c94..976d2acc 100644 --- a/src/dialogs/RoomSettings.cpp +++ b/src/dialogs/RoomSettings.cpp @@ -15,18 +15,17 @@ using namespace dialogs; -RoomSettings::RoomSettings(const QString &room_id, QSharedPointer cache, QWidget *parent) +RoomSettings::RoomSettings(const QString &room_id, QWidget *parent) : QFrame(parent) - , cache_{cache} , room_id_{std::move(room_id)} { setMaximumWidth(385); try { - auto res = cache_->getRoomInfo({room_id_.toStdString()}); + auto res = cache::client()->getRoomInfo({room_id_.toStdString()}); info_ = res[room_id_]; - setAvatar(QImage::fromData(cache_->image(info_.avatar_url))); + setAvatar(QImage::fromData(cache::client()->image(info_.avatar_url))); } catch (const lmdb::error &e) { qWarning() << "failed to retrieve room info from cache" << room_id; }