mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-29 14:18:49 +03:00
parent
ece20dd917
commit
33f534c6f8
7 changed files with 107 additions and 14 deletions
|
@ -48,6 +48,9 @@ public:
|
||||||
bool isFormatValid();
|
bool isFormatValid();
|
||||||
void setCurrentFormat();
|
void setCurrentFormat();
|
||||||
|
|
||||||
|
QByteArray image(const QString &url) const;
|
||||||
|
void saveImage(const QString &url, const QByteArray &data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setNextBatchToken(lmdb::txn &txn, const QString &token);
|
void setNextBatchToken(lmdb::txn &txn, const QString &token);
|
||||||
void insertRoomState(lmdb::txn &txn, const QString &roomid, const RoomState &state);
|
void insertRoomState(lmdb::txn &txn, const QString &roomid, const RoomState &state);
|
||||||
|
@ -56,6 +59,7 @@ private:
|
||||||
lmdb::dbi stateDb_;
|
lmdb::dbi stateDb_;
|
||||||
lmdb::dbi roomDb_;
|
lmdb::dbi roomDb_;
|
||||||
lmdb::dbi invitesDb_;
|
lmdb::dbi invitesDb_;
|
||||||
|
lmdb::dbi imagesDb_;
|
||||||
|
|
||||||
bool isMounted_;
|
bool isMounted_;
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,10 @@ signals:
|
||||||
void fileUploaded(const QString &roomid, const QString &filename, const QString &url);
|
void fileUploaded(const QString &roomid, const QString &filename, const QString &url);
|
||||||
void audioUploaded(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 userAvatarRetrieved(const QString &userId, const QImage &img);
|
||||||
void ownAvatarRetrieved(const QPixmap &img);
|
void ownAvatarRetrieved(const QPixmap &img);
|
||||||
void imageDownloaded(const QString &event_id, const QPixmap &img);
|
void imageDownloaded(const QString &event_id, const QPixmap &img);
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
class LeaveRoomDialog;
|
class LeaveRoomDialog;
|
||||||
class MatrixClient;
|
class MatrixClient;
|
||||||
|
class Cache;
|
||||||
class OverlayModal;
|
class OverlayModal;
|
||||||
class RoomInfoListItem;
|
class RoomInfoListItem;
|
||||||
class RoomSettings;
|
class RoomSettings;
|
||||||
|
@ -45,6 +46,7 @@ public:
|
||||||
RoomList(QSharedPointer<MatrixClient> client, QWidget *parent = 0);
|
RoomList(QSharedPointer<MatrixClient> client, QWidget *parent = 0);
|
||||||
~RoomList();
|
~RoomList();
|
||||||
|
|
||||||
|
void setCache(QSharedPointer<Cache> cache) { cache_ = cache; }
|
||||||
void setInitialRooms(const QMap<QString, QSharedPointer<RoomSettings>> &settings,
|
void setInitialRooms(const QMap<QString, QSharedPointer<RoomSettings>> &settings,
|
||||||
const QMap<QString, RoomState> &states);
|
const QMap<QString, RoomState> &states);
|
||||||
void sync(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 syncInvites(const std::map<std::string, mtx::responses::InvitedRoom> &rooms);
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
void updateAvatar(const QString &room_id, const QString &url);
|
||||||
|
|
||||||
void addRoom(const QMap<QString, QSharedPointer<RoomSettings>> &settings,
|
void addRoom(const QMap<QString, QSharedPointer<RoomSettings>> &settings,
|
||||||
const RoomState &state,
|
const RoomState &state,
|
||||||
|
@ -64,6 +67,7 @@ signals:
|
||||||
void totalUnreadMessageCountUpdated(int count);
|
void totalUnreadMessageCountUpdated(int count);
|
||||||
void acceptInvite(const QString &room_id);
|
void acceptInvite(const QString &room_id);
|
||||||
void declineInvite(const QString &room_id);
|
void declineInvite(const QString &room_id);
|
||||||
|
void roomAvatarChanged(const QString &room_id, const QPixmap &img);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateRoomAvatar(const QString &roomid, const QPixmap &img);
|
void updateRoomAvatar(const QString &roomid, const QPixmap &img);
|
||||||
|
@ -96,4 +100,5 @@ private:
|
||||||
QMap<QString, QSharedPointer<RoomInfoListItem>> rooms_;
|
QMap<QString, QSharedPointer<RoomInfoListItem>> rooms_;
|
||||||
|
|
||||||
QSharedPointer<MatrixClient> client_;
|
QSharedPointer<MatrixClient> client_;
|
||||||
|
QSharedPointer<Cache> cache_;
|
||||||
};
|
};
|
||||||
|
|
52
src/Cache.cc
52
src/Cache.cc
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
@ -34,6 +35,7 @@ Cache::Cache(const QString &userId)
|
||||||
, stateDb_{0}
|
, stateDb_{0}
|
||||||
, roomDb_{0}
|
, roomDb_{0}
|
||||||
, invitesDb_{0}
|
, invitesDb_{0}
|
||||||
|
, imagesDb_{0}
|
||||||
, isMounted_{false}
|
, isMounted_{false}
|
||||||
, userId_{userId}
|
, userId_{userId}
|
||||||
{}
|
{}
|
||||||
|
@ -54,7 +56,7 @@ Cache::setup()
|
||||||
bool isInitial = !QFile::exists(statePath);
|
bool isInitial = !QFile::exists(statePath);
|
||||||
|
|
||||||
env_ = lmdb::env::create();
|
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);
|
env_.set_max_dbs(1024UL);
|
||||||
|
|
||||||
if (isInitial) {
|
if (isInitial) {
|
||||||
|
@ -91,12 +93,60 @@ Cache::setup()
|
||||||
stateDb_ = lmdb::dbi::open(txn, "state", MDB_CREATE);
|
stateDb_ = lmdb::dbi::open(txn, "state", MDB_CREATE);
|
||||||
roomDb_ = lmdb::dbi::open(txn, "rooms", MDB_CREATE);
|
roomDb_ = lmdb::dbi::open(txn, "rooms", MDB_CREATE);
|
||||||
invitesDb_ = lmdb::dbi::open(txn, "invites", MDB_CREATE);
|
invitesDb_ = lmdb::dbi::open(txn, "invites", MDB_CREATE);
|
||||||
|
imagesDb_ = lmdb::dbi::open(txn, "images", MDB_CREATE);
|
||||||
|
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
|
||||||
isMounted_ = true;
|
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
|
void
|
||||||
Cache::setState(const QString &nextBatchToken, const QMap<QString, RoomState> &states)
|
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);
|
view_manager_->queueAudioMessage(roomid, filename, url);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(
|
connect(room_list_, &RoomList::roomAvatarChanged, this, &ChatPage::updateTopBarAvatar);
|
||||||
client_.data(), &MatrixClient::roomAvatarRetrieved, this, &ChatPage::updateTopBarAvatar);
|
|
||||||
|
|
||||||
connect(client_.data(),
|
connect(client_.data(),
|
||||||
&MatrixClient::initialSyncCompleted,
|
&MatrixClient::initialSyncCompleted,
|
||||||
|
@ -353,6 +352,7 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token)
|
||||||
client_->getOwnProfile();
|
client_->getOwnProfile();
|
||||||
|
|
||||||
cache_ = QSharedPointer<Cache>(new Cache(userid));
|
cache_ = QSharedPointer<Cache>(new Cache(userid));
|
||||||
|
room_list_->setCache(cache_);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cache_->setup();
|
cache_->setup();
|
||||||
|
|
|
@ -468,7 +468,7 @@ MatrixClient::fetchRoomAvatar(const QString &roomid, const QUrl &avatar_url)
|
||||||
QNetworkRequest avatar_request(endpoint);
|
QNetworkRequest avatar_request(endpoint);
|
||||||
|
|
||||||
QNetworkReply *reply = get(avatar_request);
|
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();
|
reply->deleteLater();
|
||||||
|
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
@ -486,7 +486,7 @@ MatrixClient::fetchRoomAvatar(const QString &roomid, const QUrl &avatar_url)
|
||||||
QPixmap pixmap;
|
QPixmap pixmap;
|
||||||
pixmap.loadFromData(img);
|
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/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <QBuffer>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "Cache.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "MatrixClient.h"
|
#include "MatrixClient.h"
|
||||||
#include "OverlayModal.h"
|
#include "OverlayModal.h"
|
||||||
|
@ -53,9 +55,17 @@ RoomList::RoomList(QSharedPointer<MatrixClient> client, QWidget *parent)
|
||||||
topLayout_->addWidget(scrollArea_);
|
topLayout_->addWidget(scrollArea_);
|
||||||
|
|
||||||
connect(client_.data(),
|
connect(client_.data(),
|
||||||
SIGNAL(roomAvatarRetrieved(const QString &, const QPixmap &)),
|
&MatrixClient::roomAvatarRetrieved,
|
||||||
this,
|
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() {}
|
RoomList::~RoomList() {}
|
||||||
|
@ -79,12 +89,33 @@ RoomList::addRoom(const QMap<QString, QSharedPointer<RoomSettings>> &settings,
|
||||||
rooms_.insert(room_id, QSharedPointer<RoomInfoListItem>(room_item));
|
rooms_.insert(room_id, QSharedPointer<RoomInfoListItem>(room_item));
|
||||||
|
|
||||||
if (!state.getAvatar().toString().isEmpty())
|
if (!state.getAvatar().toString().isEmpty())
|
||||||
client_->fetchRoomAvatar(room_id, state.getAvatar());
|
updateAvatar(room_id, state.getAvatar().toString());
|
||||||
|
|
||||||
int pos = contentsLayout_->count() - 1;
|
int pos = contentsLayout_->count() - 1;
|
||||||
contentsLayout_->insertWidget(pos, room_item);
|
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
|
void
|
||||||
RoomList::removeRoom(const QString &room_id, bool reset)
|
RoomList::removeRoom(const QString &room_id, bool reset)
|
||||||
{
|
{
|
||||||
|
@ -194,7 +225,7 @@ RoomList::sync(const QMap<QString, RoomState> &states,
|
||||||
auto new_avatar = state.getAvatar();
|
auto new_avatar = state.getAvatar();
|
||||||
|
|
||||||
if (current_avatar != new_avatar && !new_avatar.toString().isEmpty())
|
if (current_avatar != new_avatar && !new_avatar.toString().isEmpty())
|
||||||
client_->fetchRoomAvatar(room_id, new_avatar);
|
updateAvatar(room_id, new_avatar.toString());
|
||||||
|
|
||||||
room->setState(state);
|
room->setState(state);
|
||||||
}
|
}
|
||||||
|
@ -246,6 +277,9 @@ RoomList::updateRoomAvatar(const QString &roomid, const QPixmap &img)
|
||||||
}
|
}
|
||||||
|
|
||||||
rooms_.value(roomid)->setAvatar(img.toImage());
|
rooms_.value(roomid)->setAvatar(img.toImage());
|
||||||
|
|
||||||
|
// Used to inform other widgets for the new image data.
|
||||||
|
emit roomAvatarChanged(roomid, img);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -308,10 +342,7 @@ RoomList::addInvitedRoom(const QString &room_id, const mtx::responses::InvitedRo
|
||||||
|
|
||||||
rooms_.insert(room_id, QSharedPointer<RoomInfoListItem>(room_item));
|
rooms_.insert(room_id, QSharedPointer<RoomInfoListItem>(room_item));
|
||||||
|
|
||||||
auto avatarUrl = QString::fromStdString(room.avatar());
|
updateAvatar(room_id, QString::fromStdString(room.avatar()));
|
||||||
|
|
||||||
if (!avatarUrl.isEmpty())
|
|
||||||
client_->fetchRoomAvatar(room_id, avatarUrl);
|
|
||||||
|
|
||||||
int pos = contentsLayout_->count() - 1;
|
int pos = contentsLayout_->count() - 1;
|
||||||
contentsLayout_->insertWidget(pos, room_item);
|
contentsLayout_->insertWidget(pos, room_item);
|
||||||
|
|
Loading…
Reference in a new issue