diff --git a/src/Cache.cc b/src/Cache.cc
index 4e2f32a9..06e45f13 100644
--- a/src/Cache.cc
+++ b/src/Cache.cc
@@ -17,6 +17,7 @@
#include <stdexcept>
+#include <QByteArray>
#include <QDebug>
#include <QFile>
#include <QStandardPaths>
@@ -34,6 +35,7 @@ Cache::Cache(const QString &userId)
, stateDb_{0}
, roomDb_{0}
, invitesDb_{0}
+ , imagesDb_{0}
, isMounted_{false}
, userId_{userId}
{}
@@ -54,7 +56,7 @@ Cache::setup()
bool isInitial = !QFile::exists(statePath);
env_ = lmdb::env::create();
- env_.set_mapsize(128UL * 1024UL * 1024UL); /* 128 MB */
+ env_.set_mapsize(256UL * 1024UL * 1024UL); /* 256 MB */
env_.set_max_dbs(1024UL);
if (isInitial) {
@@ -91,6 +93,7 @@ Cache::setup()
stateDb_ = lmdb::dbi::open(txn, "state", MDB_CREATE);
roomDb_ = lmdb::dbi::open(txn, "rooms", MDB_CREATE);
invitesDb_ = lmdb::dbi::open(txn, "invites", MDB_CREATE);
+ imagesDb_ = lmdb::dbi::open(txn, "images", MDB_CREATE);
txn.commit();
@@ -98,6 +101,53 @@ Cache::setup()
}
void
+Cache::saveImage(const QString &url, const QByteArray &image)
+{
+ if (!isMounted_)
+ return;
+
+ auto key = url.toUtf8();
+
+ try {
+ auto txn = lmdb::txn::begin(env_);
+
+ lmdb::dbi_put(txn,
+ imagesDb_,
+ lmdb::val(key.data(), key.size()),
+ lmdb::val(image.data(), image.size()));
+
+ txn.commit();
+ } catch (const lmdb::error &e) {
+ qCritical() << "saveImage:" << e.what();
+ }
+}
+
+QByteArray
+Cache::image(const QString &url) const
+{
+ auto key = url.toUtf8();
+
+ try {
+ auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY);
+
+ lmdb::val image;
+
+ bool res = lmdb::dbi_get(txn, imagesDb_, lmdb::val(key.data(), key.size()), image);
+
+ txn.commit();
+
+ if (!res)
+ return QByteArray();
+
+ return QByteArray(image.data(), image.size());
+ } catch (const lmdb::error &e) {
+ qCritical() << "image:" << e.what();
+ }
+
+ return QByteArray();
+}
+
+void
Cache::setState(const QString &nextBatchToken, const QMap<QString, RoomState> &states)
{
if (!isMounted_)
diff --git a/src/ChatPage.cc b/src/ChatPage.cc
index a5b36d81..8161d62c 100644
--- a/src/ChatPage.cc
+++ b/src/ChatPage.cc
@@ -232,8 +232,7 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
view_manager_->queueAudioMessage(roomid, filename, url);
});
- connect(
- client_.data(), &MatrixClient::roomAvatarRetrieved, this, &ChatPage::updateTopBarAvatar);
+ connect(room_list_, &RoomList::roomAvatarChanged, this, &ChatPage::updateTopBarAvatar);
connect(client_.data(),
&MatrixClient::initialSyncCompleted,
@@ -353,6 +352,7 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token)
client_->getOwnProfile();
cache_ = QSharedPointer<Cache>(new Cache(userid));
+ room_list_->setCache(cache_);
try {
cache_->setup();
diff --git a/src/MatrixClient.cc b/src/MatrixClient.cc
index b5dfe514..1b2e020d 100644
--- a/src/MatrixClient.cc
+++ b/src/MatrixClient.cc
@@ -468,7 +468,7 @@ MatrixClient::fetchRoomAvatar(const QString &roomid, const QUrl &avatar_url)
QNetworkRequest avatar_request(endpoint);
QNetworkReply *reply = get(avatar_request);
- connect(reply, &QNetworkReply::finished, this, [this, reply, roomid]() {
+ connect(reply, &QNetworkReply::finished, this, [this, reply, roomid, avatar_url]() {
reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
@@ -486,7 +486,7 @@ MatrixClient::fetchRoomAvatar(const QString &roomid, const QUrl &avatar_url)
QPixmap pixmap;
pixmap.loadFromData(img);
- emit roomAvatarRetrieved(roomid, pixmap);
+ emit roomAvatarRetrieved(roomid, pixmap, avatar_url.toString(), img);
});
}
diff --git a/src/RoomList.cc b/src/RoomList.cc
index 1e639838..ea13d700 100644
--- a/src/RoomList.cc
+++ b/src/RoomList.cc
@@ -15,9 +15,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <QBuffer>
#include <QDebug>
#include <QObject>
+#include "Cache.h"
#include "MainWindow.h"
#include "MatrixClient.h"
#include "OverlayModal.h"
@@ -53,9 +55,17 @@ RoomList::RoomList(QSharedPointer<MatrixClient> client, QWidget *parent)
topLayout_->addWidget(scrollArea_);
connect(client_.data(),
- SIGNAL(roomAvatarRetrieved(const QString &, const QPixmap &)),
+ &MatrixClient::roomAvatarRetrieved,
this,
- SLOT(updateRoomAvatar(const QString &, const QPixmap &)));
+ [=](const QString &room_id,
+ const QPixmap &img,
+ const QString &url,
+ const QByteArray &data) {
+ if (!cache_.isNull())
+ cache_->saveImage(url, data);
+
+ updateRoomAvatar(room_id, img);
+ });
}
RoomList::~RoomList() {}
@@ -79,13 +89,34 @@ RoomList::addRoom(const QMap<QString, QSharedPointer<RoomSettings>> &settings,
rooms_.insert(room_id, QSharedPointer<RoomInfoListItem>(room_item));
if (!state.getAvatar().toString().isEmpty())
- client_->fetchRoomAvatar(room_id, state.getAvatar());
+ updateAvatar(room_id, state.getAvatar().toString());
int pos = contentsLayout_->count() - 1;
contentsLayout_->insertWidget(pos, room_item);
}
void
+RoomList::updateAvatar(const QString &room_id, const QString &url)
+{
+ if (url.isEmpty())
+ return;
+
+ QByteArray savedImgData;
+
+ if (!cache_.isNull())
+ savedImgData = cache_->image(url);
+
+ if (savedImgData.isEmpty()) {
+ client_->fetchRoomAvatar(room_id, url);
+ } else {
+ QPixmap img;
+ img.loadFromData(savedImgData);
+
+ updateRoomAvatar(room_id, img);
+ }
+}
+
+void
RoomList::removeRoom(const QString &room_id, bool reset)
{
rooms_.remove(room_id);
@@ -194,7 +225,7 @@ RoomList::sync(const QMap<QString, RoomState> &states,
auto new_avatar = state.getAvatar();
if (current_avatar != new_avatar && !new_avatar.toString().isEmpty())
- client_->fetchRoomAvatar(room_id, new_avatar);
+ updateAvatar(room_id, new_avatar.toString());
room->setState(state);
}
@@ -246,6 +277,9 @@ RoomList::updateRoomAvatar(const QString &roomid, const QPixmap &img)
}
rooms_.value(roomid)->setAvatar(img.toImage());
+
+ // Used to inform other widgets for the new image data.
+ emit roomAvatarChanged(roomid, img);
}
void
@@ -308,10 +342,7 @@ RoomList::addInvitedRoom(const QString &room_id, const mtx::responses::InvitedRo
rooms_.insert(room_id, QSharedPointer<RoomInfoListItem>(room_item));
- auto avatarUrl = QString::fromStdString(room.avatar());
-
- if (!avatarUrl.isEmpty())
- client_->fetchRoomAvatar(room_id, avatarUrl);
+ updateAvatar(room_id, QString::fromStdString(room.avatar()));
int pos = contentsLayout_->count() - 1;
contentsLayout_->insertWidget(pos, room_item);
|