mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-25 20:48:52 +03:00
parent
ece20dd917
commit
33f534c6f8
7 changed files with 107 additions and 14 deletions
|
@ -48,6 +48,9 @@ public:
|
|||
bool isFormatValid();
|
||||
void setCurrentFormat();
|
||||
|
||||
QByteArray image(const QString &url) const;
|
||||
void saveImage(const QString &url, const QByteArray &data);
|
||||
|
||||
private:
|
||||
void setNextBatchToken(lmdb::txn &txn, const QString &token);
|
||||
void insertRoomState(lmdb::txn &txn, const QString &roomid, const RoomState &state);
|
||||
|
@ -56,6 +59,7 @@ private:
|
|||
lmdb::dbi stateDb_;
|
||||
lmdb::dbi roomDb_;
|
||||
lmdb::dbi invitesDb_;
|
||||
lmdb::dbi imagesDb_;
|
||||
|
||||
bool isMounted_;
|
||||
|
||||
|
|
|
@ -98,7 +98,10 @@ signals:
|
|||
void fileUploaded(const QString &roomid, const QString &filename, const QString &url);
|
||||
void audioUploaded(const QString &roomid, const QString &filename, const QString &url);
|
||||
|
||||
void roomAvatarRetrieved(const QString &roomid, const QPixmap &img);
|
||||
void roomAvatarRetrieved(const QString &roomid,
|
||||
const QPixmap &img,
|
||||
const QString &url,
|
||||
const QByteArray &data);
|
||||
void userAvatarRetrieved(const QString &userId, const QImage &img);
|
||||
void ownAvatarRetrieved(const QPixmap &img);
|
||||
void imageDownloaded(const QString &event_id, const QPixmap &img);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
class LeaveRoomDialog;
|
||||
class MatrixClient;
|
||||
class Cache;
|
||||
class OverlayModal;
|
||||
class RoomInfoListItem;
|
||||
class RoomSettings;
|
||||
|
@ -45,6 +46,7 @@ public:
|
|||
RoomList(QSharedPointer<MatrixClient> client, QWidget *parent = 0);
|
||||
~RoomList();
|
||||
|
||||
void setCache(QSharedPointer<Cache> cache) { cache_ = cache; }
|
||||
void setInitialRooms(const QMap<QString, QSharedPointer<RoomSettings>> &settings,
|
||||
const QMap<QString, RoomState> &states);
|
||||
void sync(const QMap<QString, RoomState> &states,
|
||||
|
@ -52,6 +54,7 @@ public:
|
|||
void syncInvites(const std::map<std::string, mtx::responses::InvitedRoom> &rooms);
|
||||
|
||||
void clear();
|
||||
void updateAvatar(const QString &room_id, const QString &url);
|
||||
|
||||
void addRoom(const QMap<QString, QSharedPointer<RoomSettings>> &settings,
|
||||
const RoomState &state,
|
||||
|
@ -64,6 +67,7 @@ signals:
|
|||
void totalUnreadMessageCountUpdated(int count);
|
||||
void acceptInvite(const QString &room_id);
|
||||
void declineInvite(const QString &room_id);
|
||||
void roomAvatarChanged(const QString &room_id, const QPixmap &img);
|
||||
|
||||
public slots:
|
||||
void updateRoomAvatar(const QString &roomid, const QPixmap &img);
|
||||
|
@ -96,4 +100,5 @@ private:
|
|||
QMap<QString, QSharedPointer<RoomInfoListItem>> rooms_;
|
||||
|
||||
QSharedPointer<MatrixClient> client_;
|
||||
QSharedPointer<Cache> cache_;
|
||||
};
|
||||
|
|
52
src/Cache.cc
52
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,12 +93,60 @@ 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();
|
||||
|
||||
isMounted_ = true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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,12 +89,33 @@ 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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue