mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 03:00:46 +03:00
Refactor image download code to be reusable
This commit is contained in:
parent
41737ac22c
commit
95026dcc62
2 changed files with 161 additions and 90 deletions
|
@ -4,106 +4,192 @@
|
|||
|
||||
#include "MxcImageProvider.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <mtxclient/crypto/client.hpp>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QFileInfo>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include "Cache.h"
|
||||
#include "Logging.h"
|
||||
#include "MatrixClient.h"
|
||||
#include "Utils.h"
|
||||
|
||||
QHash<QString, mtx::crypto::EncryptedFile> infos;
|
||||
|
||||
QQuickImageResponse *
|
||||
MxcImageProvider::requestImageResponse(const QString &id, const QSize &requestedSize)
|
||||
{
|
||||
MxcImageResponse *response = new MxcImageResponse(id, requestedSize);
|
||||
pool.start(response);
|
||||
return response;
|
||||
}
|
||||
|
||||
void
|
||||
MxcImageProvider::addEncryptionInfo(mtx::crypto::EncryptedFile info)
|
||||
{
|
||||
infos.insert(QString::fromStdString(info.url), info);
|
||||
}
|
||||
void
|
||||
MxcImageResponse::run()
|
||||
{
|
||||
if (m_requestedSize.isValid() && !m_encryptionInfo) {
|
||||
QString fileName = QString("%1_%2x%3_crop")
|
||||
.arg(m_id)
|
||||
.arg(m_requestedSize.width())
|
||||
.arg(m_requestedSize.height());
|
||||
MxcImageProvider::download(
|
||||
m_id, m_requestedSize, [this](QString, QSize, QImage image, QString) {
|
||||
if (image.isNull()) {
|
||||
m_error = "Failed to download image.";
|
||||
} else {
|
||||
m_image = image;
|
||||
}
|
||||
emit finished();
|
||||
});
|
||||
}
|
||||
|
||||
auto data = cache::image(fileName);
|
||||
if (!data.isNull()) {
|
||||
m_image = utils::readImage(data);
|
||||
void
|
||||
MxcImageProvider::download(const QString &id,
|
||||
const QSize &requestedSize,
|
||||
std::function<void(QString, QSize, QImage, QString)> then)
|
||||
{
|
||||
std::optional<mtx::crypto::EncryptedFile> encryptionInfo;
|
||||
auto temp = infos.find("mxc://" + id);
|
||||
if (temp != infos.end())
|
||||
encryptionInfo = *temp;
|
||||
|
||||
if (!m_image.isNull()) {
|
||||
m_image = m_image.scaled(
|
||||
m_requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
m_image.setText("mxc url", "mxc://" + m_id);
|
||||
if (requestedSize.isValid() && !encryptionInfo) {
|
||||
QString fileName =
|
||||
QString("%1_%2x%3_crop")
|
||||
.arg(QString::fromUtf8(id.toUtf8().toBase64(QByteArray::Base64UrlEncoding |
|
||||
QByteArray::OmitTrailingEquals)),
|
||||
requestedSize.width(),
|
||||
requestedSize.height());
|
||||
QFileInfo fileInfo(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) +
|
||||
"/media_cache",
|
||||
fileName);
|
||||
|
||||
if (!m_image.isNull()) {
|
||||
emit finished();
|
||||
if (fileInfo.exists()) {
|
||||
QImage image(fileInfo.absoluteFilePath());
|
||||
if (!image.isNull()) {
|
||||
image = image.scaled(
|
||||
requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
|
||||
if (!image.isNull()) {
|
||||
then(id, requestedSize, image, fileInfo.absoluteFilePath());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mtx::http::ThumbOpts opts;
|
||||
opts.mxc_url = "mxc://" + m_id.toStdString();
|
||||
opts.width = m_requestedSize.width() > 0 ? m_requestedSize.width() : -1;
|
||||
opts.height = m_requestedSize.height() > 0 ? m_requestedSize.height() : -1;
|
||||
opts.mxc_url = "mxc://" + id.toStdString();
|
||||
opts.width = requestedSize.width() > 0 ? requestedSize.width() : -1;
|
||||
opts.height = requestedSize.height() > 0 ? requestedSize.height() : -1;
|
||||
opts.method = "crop";
|
||||
http::client()->get_thumbnail(
|
||||
opts, [this, fileName](const std::string &res, mtx::http::RequestErr err) {
|
||||
opts,
|
||||
[fileInfo, requestedSize, then, id](const std::string &res,
|
||||
mtx::http::RequestErr err) {
|
||||
if (err || res.empty()) {
|
||||
nhlog::net()->error("Failed to download image {}",
|
||||
m_id.toStdString());
|
||||
m_error = "Failed download";
|
||||
emit finished();
|
||||
then(id, QSize(), {}, "");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto data = QByteArray(res.data(), (int)res.size());
|
||||
cache::saveImage(fileName, data);
|
||||
m_image = utils::readImage(data);
|
||||
if (!m_image.isNull()) {
|
||||
m_image = m_image.scaled(
|
||||
m_requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
auto data = QByteArray(res.data(), (int)res.size());
|
||||
QImage image = utils::readImage(data);
|
||||
if (!image.isNull()) {
|
||||
image = image.scaled(
|
||||
requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
m_image.setText("mxc url", "mxc://" + m_id);
|
||||
image.setText("mxc url", "mxc://" + id);
|
||||
image.save(fileInfo.absoluteFilePath());
|
||||
|
||||
emit finished();
|
||||
then(id, requestedSize, image, fileInfo.absoluteFilePath());
|
||||
});
|
||||
} else {
|
||||
auto data = cache::image(m_id);
|
||||
try {
|
||||
QString fileName = QString::fromUtf8(id.toUtf8().toBase64(
|
||||
QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals));
|
||||
QFileInfo fileInfo(
|
||||
QStandardPaths::writableLocation(QStandardPaths::CacheLocation) +
|
||||
"/media_cache",
|
||||
fileName);
|
||||
|
||||
if (!data.isNull()) {
|
||||
m_image = utils::readImage(data);
|
||||
m_image.setText("mxc url", "mxc://" + m_id);
|
||||
if (fileInfo.exists()) {
|
||||
if (encryptionInfo) {
|
||||
QFile f(fileInfo.absoluteFilePath());
|
||||
f.open(QIODevice::ReadOnly);
|
||||
|
||||
if (!m_image.isNull()) {
|
||||
emit finished();
|
||||
return;
|
||||
QByteArray fileData = f.readAll();
|
||||
auto temp =
|
||||
mtx::crypto::to_string(mtx::crypto::decrypt_file(
|
||||
fileData.toStdString(), encryptionInfo.value()));
|
||||
auto data = QByteArray(temp.data(), (int)temp.size());
|
||||
QImage image = utils::readImage(data);
|
||||
image.setText("mxc url", "mxc://" + id);
|
||||
if (!image.isNull()) {
|
||||
then(id,
|
||||
requestedSize,
|
||||
image,
|
||||
fileInfo.absoluteFilePath());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
QImage image(fileInfo.absoluteFilePath());
|
||||
if (!image.isNull()) {
|
||||
then(id,
|
||||
requestedSize,
|
||||
image,
|
||||
fileInfo.absoluteFilePath());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto data = cache::image(id);
|
||||
|
||||
http::client()->download(
|
||||
"mxc://" + id.toStdString(),
|
||||
[fileInfo, requestedSize, then, id, encryptionInfo](
|
||||
const std::string &res,
|
||||
const std::string &,
|
||||
const std::string &originalFilename,
|
||||
mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
then(id, QSize(), {}, "");
|
||||
return;
|
||||
}
|
||||
|
||||
auto temp = res;
|
||||
QFile f(fileInfo.absoluteFilePath());
|
||||
if (!f.open(QIODevice::Truncate | QIODevice::WriteOnly)) {
|
||||
then(id, QSize(), {}, "");
|
||||
return;
|
||||
}
|
||||
f.write(temp.data(), temp.size());
|
||||
f.close();
|
||||
|
||||
if (encryptionInfo) {
|
||||
temp = mtx::crypto::to_string(mtx::crypto::decrypt_file(
|
||||
temp, encryptionInfo.value()));
|
||||
auto data = QByteArray(temp.data(), (int)temp.size());
|
||||
QImage image = utils::readImage(data);
|
||||
image.setText("original filename",
|
||||
QString::fromStdString(originalFilename));
|
||||
image.setText("mxc url", "mxc://" + id);
|
||||
then(
|
||||
id, requestedSize, image, fileInfo.absoluteFilePath());
|
||||
return;
|
||||
}
|
||||
|
||||
QImage image(fileInfo.absoluteFilePath());
|
||||
image.setText("original filename",
|
||||
QString::fromStdString(originalFilename));
|
||||
image.setText("mxc url", "mxc://" + id);
|
||||
image.save(fileInfo.absoluteFilePath());
|
||||
then(id, requestedSize, image, fileInfo.absoluteFilePath());
|
||||
});
|
||||
} catch (std::exception &e) {
|
||||
nhlog::net()->error("Exception while downloading media: {}", e.what());
|
||||
}
|
||||
|
||||
http::client()->download(
|
||||
"mxc://" + m_id.toStdString(),
|
||||
[this](const std::string &res,
|
||||
const std::string &,
|
||||
const std::string &originalFilename,
|
||||
mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::net()->error("Failed to download image {}",
|
||||
m_id.toStdString());
|
||||
m_error = "Failed download";
|
||||
emit finished();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto temp = res;
|
||||
if (m_encryptionInfo)
|
||||
temp = mtx::crypto::to_string(
|
||||
mtx::crypto::decrypt_file(temp, m_encryptionInfo.value()));
|
||||
|
||||
auto data = QByteArray(temp.data(), (int)temp.size());
|
||||
cache::saveImage(m_id, data);
|
||||
m_image = utils::readImage(data);
|
||||
m_image.setText("original filename",
|
||||
QString::fromStdString(originalFilename));
|
||||
m_image.setText("mxc url", "mxc://" + m_id);
|
||||
|
||||
emit finished();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,21 +10,18 @@
|
|||
#include <QImage>
|
||||
#include <QThreadPool>
|
||||
|
||||
#include <mtx/common.hpp>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <mtx/common.hpp>
|
||||
|
||||
class MxcImageResponse
|
||||
: public QQuickImageResponse
|
||||
, public QRunnable
|
||||
{
|
||||
public:
|
||||
MxcImageResponse(const QString &id,
|
||||
const QSize &requestedSize,
|
||||
boost::optional<mtx::crypto::EncryptedFile> encryptionInfo)
|
||||
MxcImageResponse(const QString &id, const QSize &requestedSize)
|
||||
: m_id(id)
|
||||
, m_requestedSize(requestedSize)
|
||||
, m_encryptionInfo(encryptionInfo)
|
||||
{
|
||||
setAutoDelete(false);
|
||||
}
|
||||
|
@ -40,7 +37,6 @@ public:
|
|||
QString m_id, m_error;
|
||||
QSize m_requestedSize;
|
||||
QImage m_image;
|
||||
boost::optional<mtx::crypto::EncryptedFile> m_encryptionInfo;
|
||||
};
|
||||
|
||||
class MxcImageProvider
|
||||
|
@ -50,24 +46,13 @@ class MxcImageProvider
|
|||
Q_OBJECT
|
||||
public slots:
|
||||
QQuickImageResponse *requestImageResponse(const QString &id,
|
||||
const QSize &requestedSize) override
|
||||
{
|
||||
boost::optional<mtx::crypto::EncryptedFile> info;
|
||||
auto temp = infos.find("mxc://" + id);
|
||||
if (temp != infos.end())
|
||||
info = *temp;
|
||||
const QSize &requestedSize) override;
|
||||
|
||||
MxcImageResponse *response = new MxcImageResponse(id, requestedSize, info);
|
||||
pool.start(response);
|
||||
return response;
|
||||
}
|
||||
|
||||
void addEncryptionInfo(mtx::crypto::EncryptedFile info)
|
||||
{
|
||||
infos.insert(QString::fromStdString(info.url), info);
|
||||
}
|
||||
static void addEncryptionInfo(mtx::crypto::EncryptedFile info);
|
||||
static void download(const QString &id,
|
||||
const QSize &requestedSize,
|
||||
std::function<void(QString, QSize, QImage, QString)> then);
|
||||
|
||||
private:
|
||||
QThreadPool pool;
|
||||
QHash<QString, mtx::crypto::EncryptedFile> infos;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue