mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-25 20:48:52 +03:00
Implement media cache
This commit is contained in:
parent
54091cf403
commit
29bd8b71d1
6 changed files with 63 additions and 35 deletions
|
@ -24,23 +24,26 @@
|
|||
|
||||
class MatrixClient;
|
||||
class TimelineItem;
|
||||
class Cache;
|
||||
|
||||
class AvatarProvider : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static void init(QSharedPointer<MatrixClient> client) { client_ = client; }
|
||||
static void init(QSharedPointer<MatrixClient> client, QSharedPointer<Cache> cache)
|
||||
{
|
||||
client_ = client;
|
||||
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<void(QImage)> callback);
|
||||
//! Remove all saved data.
|
||||
static void clear() { avatars_.clear(); };
|
||||
|
||||
private:
|
||||
static QSharedPointer<MatrixClient> client_;
|
||||
static QHash<QString, QImage> avatars_;
|
||||
static QSharedPointer<Cache> cache_;
|
||||
};
|
||||
|
|
|
@ -51,8 +51,8 @@ constexpr int CONSENSUS_TIMEOUT = 1000;
|
|||
constexpr int SHOW_CONTENT_TIMEOUT = 3000;
|
||||
constexpr int TYPING_REFRESH_TIMEOUT = 10000;
|
||||
|
||||
Q_DECLARE_METATYPE(mtx::responses::Rooms);
|
||||
Q_DECLARE_METATYPE(std::vector<std::string>);
|
||||
Q_DECLARE_METATYPE(mtx::responses::Rooms)
|
||||
Q_DECLARE_METATYPE(std::vector<std::string>)
|
||||
|
||||
class ChatPage : public QWidget
|
||||
{
|
||||
|
|
|
@ -15,12 +15,15 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QtConcurrent>
|
||||
|
||||
#include "AvatarProvider.h"
|
||||
#include "Cache.h"
|
||||
#include "MatrixClient.h"
|
||||
|
||||
QSharedPointer<MatrixClient> AvatarProvider::client_;
|
||||
QHash<QString, QImage> AvatarProvider::avatars_;
|
||||
QSharedPointer<Cache> AvatarProvider::cache_;
|
||||
|
||||
void
|
||||
AvatarProvider::resolve(const QString &room_id,
|
||||
|
@ -28,21 +31,22 @@ AvatarProvider::resolve(const QString &room_id,
|
|||
QObject *receiver,
|
||||
std::function<void(QImage)> callback)
|
||||
{
|
||||
const auto key = QString("%1 %2").arg(room_id).arg(user_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))
|
||||
if (!Cache::AvatarUrls.contains(key) || cache_.isNull())
|
||||
return;
|
||||
|
||||
if (avatars_.contains(key)) {
|
||||
auto img = avatars_[key];
|
||||
if (avatarUrl.isEmpty())
|
||||
return;
|
||||
|
||||
if (!img.isNull()) {
|
||||
callback(img);
|
||||
return;
|
||||
}
|
||||
auto data = cache_->image(avatarUrl);
|
||||
if (!data.isNull()) {
|
||||
callback(QImage::fromData(data));
|
||||
return;
|
||||
}
|
||||
|
||||
auto proxy = client_->fetchUserAvatar(Cache::avatarUrl(room_id, user_id));
|
||||
auto proxy = client_->fetchUserAvatar(avatarUrl);
|
||||
|
||||
if (proxy.isNull())
|
||||
return;
|
||||
|
@ -50,9 +54,16 @@ AvatarProvider::resolve(const QString &room_id,
|
|||
connect(proxy.data(),
|
||||
&DownloadMediaProxy::avatarDownloaded,
|
||||
receiver,
|
||||
[user_id, proxy, callback, key](const QImage &img) {
|
||||
[user_id, proxy, callback, avatarUrl](const QImage &img) {
|
||||
proxy->deleteLater();
|
||||
avatars_.insert(key, img);
|
||||
QtConcurrent::run([img, avatarUrl]() {
|
||||
QByteArray data;
|
||||
QBuffer buffer(&data);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
img.save(&buffer, "PNG");
|
||||
|
||||
cache_->saveImage(avatarUrl, data);
|
||||
});
|
||||
callback(img);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -144,6 +144,9 @@ Cache::saveImage(const QString &url, const QByteArray &image)
|
|||
QByteArray
|
||||
Cache::image(const QString &url) const
|
||||
{
|
||||
if (url.isEmpty())
|
||||
return QByteArray();
|
||||
|
||||
auto key = url.toUtf8();
|
||||
|
||||
try {
|
||||
|
@ -160,7 +163,7 @@ Cache::image(const QString &url) const
|
|||
|
||||
return QByteArray(image.data(), image.size());
|
||||
} catch (const lmdb::error &e) {
|
||||
qCritical() << "image:" << e.what();
|
||||
qCritical() << "image:" << e.what() << url;
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
|
|
|
@ -399,8 +399,6 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client,
|
|||
this,
|
||||
&ChatPage::setGroupViewState);
|
||||
|
||||
AvatarProvider::init(client);
|
||||
|
||||
connect(this, &ChatPage::continueSync, this, [this](const QString &next_batch) {
|
||||
syncTimeoutTimer_->start(SYNC_RETRY_TIMEOUT);
|
||||
client_->setNextBatchToken(next_batch);
|
||||
|
@ -461,7 +459,6 @@ ChatPage::resetUI()
|
|||
top_bar_->reset();
|
||||
user_info_widget_->reset();
|
||||
view_manager_->clearAll();
|
||||
AvatarProvider::clear();
|
||||
|
||||
showUnreadMessageNotification(0);
|
||||
}
|
||||
|
@ -497,6 +494,8 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token)
|
|||
room_list_->setCache(cache_);
|
||||
text_input_->setCache(cache_);
|
||||
|
||||
AvatarProvider::init(client_, cache_);
|
||||
|
||||
try {
|
||||
cache_->setup();
|
||||
|
||||
|
@ -584,21 +583,30 @@ ChatPage::updateOwnProfileInfo(const QUrl &avatar_url, const QString &display_na
|
|||
user_info_widget_->setUserId(userid);
|
||||
user_info_widget_->setDisplayName(display_name);
|
||||
|
||||
if (avatar_url.isValid()) {
|
||||
auto proxy = client_->fetchUserAvatar(avatar_url);
|
||||
if (!avatar_url.isValid())
|
||||
return;
|
||||
|
||||
if (proxy.isNull())
|
||||
if (!cache_.isNull()) {
|
||||
auto data = cache_->image(avatar_url.toString());
|
||||
if (!data.isNull()) {
|
||||
user_info_widget_->setAvatar(QImage::fromData(data));
|
||||
return;
|
||||
|
||||
proxy->setParent(this);
|
||||
connect(proxy.data(),
|
||||
&DownloadMediaProxy::avatarDownloaded,
|
||||
this,
|
||||
[this, proxy](const QImage &img) {
|
||||
proxy->deleteLater();
|
||||
user_info_widget_->setAvatar(img);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
auto proxy = client_->fetchUserAvatar(avatar_url);
|
||||
|
||||
if (proxy.isNull())
|
||||
return;
|
||||
|
||||
proxy->setParent(this);
|
||||
connect(proxy.data(),
|
||||
&DownloadMediaProxy::avatarDownloaded,
|
||||
this,
|
||||
[this, proxy](const QImage &img) {
|
||||
proxy->deleteLater();
|
||||
user_info_widget_->setAvatar(img);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -661,8 +669,8 @@ ChatPage::loadStateFromCache()
|
|||
try {
|
||||
cache_->populateMembers();
|
||||
|
||||
emit initializeRoomList(cache_->roomInfo());
|
||||
emit initializeEmptyViews(cache_->joinedRooms());
|
||||
emit initializeRoomList(cache_->roomInfo());
|
||||
} catch (const lmdb::error &e) {
|
||||
std::cout << "load cache error:" << e.what() << '\n';
|
||||
// TODO Clear cache and restart.
|
||||
|
|
|
@ -621,6 +621,9 @@ MatrixClient::fetchRoomAvatar(const QString &roomid, const QUrl &avatar_url)
|
|||
void
|
||||
MatrixClient::fetchCommunityAvatar(const QString &communityId, const QUrl &avatar_url)
|
||||
{
|
||||
if (avatar_url.isEmpty())
|
||||
return;
|
||||
|
||||
QList<QString> url_parts = avatar_url.toString().split("mxc://");
|
||||
|
||||
if (url_parts.size() != 2) {
|
||||
|
|
Loading…
Reference in a new issue