diff --git a/src/MxcImageProvider.cpp b/src/MxcImageProvider.cpp
index 35cd0c45..db0f72c9 100644
--- a/src/MxcImageProvider.cpp
+++ b/src/MxcImageProvider.cpp
@@ -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());
-
- auto data = cache::image(fileName);
- if (!data.isNull()) {
- m_image = utils::readImage(data);
-
- if (!m_image.isNull()) {
- m_image = m_image.scaled(
- m_requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
- m_image.setText("mxc url", "mxc://" + m_id);
-
- if (!m_image.isNull()) {
- emit finished();
+ 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();
+ });
+}
+
+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 (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 (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);
-
- if (!data.isNull()) {
- m_image = utils::readImage(data);
- m_image.setText("mxc url", "mxc://" + m_id);
-
- if (!m_image.isNull()) {
- emit finished();
- return;
+ try {
+ QString fileName = QString::fromUtf8(id.toUtf8().toBase64(
+ QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals));
+ QFileInfo fileInfo(
+ QStandardPaths::writableLocation(QStandardPaths::CacheLocation) +
+ "/media_cache",
+ fileName);
+
+ if (fileInfo.exists()) {
+ if (encryptionInfo) {
+ QFile f(fileInfo.absoluteFilePath());
+ f.open(QIODevice::ReadOnly);
+
+ 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();
- });
}
}
diff --git a/src/MxcImageProvider.h b/src/MxcImageProvider.h
index f7580bca..7b960836 100644
--- a/src/MxcImageProvider.h
+++ b/src/MxcImageProvider.h
@@ -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;
};
|