diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h
index 20c3d17e..28a4bcf6 100644
--- a/src/timeline/InputBar.h
+++ b/src/timeline/InputBar.h
@@ -5,10 +5,17 @@
#pragma once
+#include <QAbstractVideoSurface>
+#include <QIODevice>
+#include <QImage>
#include <QObject>
+#include <QSize>
#include <QStringList>
#include <QTimer>
+#include <QUrl>
+#include <QVariantList>
#include <deque>
+#include <memory>
#include <mtx/common.hpp>
#include <mtx/responses/messages.hpp>
@@ -25,12 +32,139 @@ enum class MarkdownOverride
OFF,
};
+class InputVideoSurface : public QAbstractVideoSurface
+{
+ Q_OBJECT
+
+public:
+ InputVideoSurface(QObject *parent)
+ : QAbstractVideoSurface(parent)
+ {}
+
+ bool present(const QVideoFrame &frame) override;
+
+ QList<QVideoFrame::PixelFormat>
+ supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const override;
+
+signals:
+ void newImage(QImage img);
+};
+
+class MediaUpload : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int mediaType READ type NOTIFY mediaTypeChanged)
+ // https://stackoverflow.com/questions/33422265/pass-qimage-to-qml/68554646#68554646
+ Q_PROPERTY(QUrl thumbnail READ thumbnailDataUrl NOTIFY thumbnailChanged)
+ // Q_PROPERTY(QString humanSize READ humanSize NOTIFY huSizeChanged)
+ Q_PROPERTY(QString filename READ filename WRITE setFilename NOTIFY filenameChanged)
+
+ // thumbnail video
+ // https://stackoverflow.com/questions/26229633/display-on-screen-using-qabstractvideosurface
+
+public:
+ enum MediaType
+ {
+ File,
+ Image,
+ Video,
+ Audio,
+ };
+ Q_ENUM(MediaType)
+
+ explicit MediaUpload(std::unique_ptr<QIODevice> data,
+ QString mimetype,
+ QString originalFilename,
+ bool encrypt,
+ QObject *parent = nullptr);
+
+ [[nodiscard]] int type() const
+ {
+ if (mimeClass_ == u"video")
+ return MediaType::Video;
+ else if (mimeClass_ == u"audio")
+ return MediaType::Audio;
+ else if (mimeClass_ == u"image")
+ return MediaType::Image;
+ else
+ return MediaType::File;
+ }
+ [[nodiscard]] QString url() const { return url_; }
+ [[nodiscard]] QString mimetype() const { return mimetype_; }
+ [[nodiscard]] QString mimeClass() const { return mimeClass_; }
+ [[nodiscard]] QString filename() const { return originalFilename_; }
+ [[nodiscard]] QString blurhash() const { return blurhash_; }
+ [[nodiscard]] uint64_t size() const { return size_; }
+ [[nodiscard]] uint64_t duration() const { return duration_; }
+ [[nodiscard]] std::optional<mtx::crypto::EncryptedFile> encryptedFile_()
+ {
+ return encryptedFile;
+ }
+ [[nodiscard]] std::optional<mtx::crypto::EncryptedFile> thumbnailEncryptedFile_()
+ {
+ return thumbnailEncryptedFile;
+ }
+ [[nodiscard]] QSize dimensions() const { return dimensions_; }
+
+ QImage thumbnailImg() const { return thumbnail_; }
+ QString thumbnailUrl() const { return thumbnailUrl_; }
+ QUrl thumbnailDataUrl() const;
+ [[nodiscard]] uint64_t thumbnailSize() const { return thumbnailSize_; }
+
+ void setFilename(QString fn)
+ {
+ if (fn != originalFilename_) {
+ originalFilename_ = std::move(fn);
+ emit filenameChanged();
+ }
+ }
+
+signals:
+ void uploadComplete(MediaUpload *self, QString url);
+ void uploadFailed(MediaUpload *self);
+ void filenameChanged();
+ void thumbnailChanged();
+ void mediaTypeChanged();
+
+public slots:
+ void startUpload();
+
+private slots:
+ void setThumbnail(QImage img)
+ {
+ this->thumbnail_ = std::move(img);
+ emit thumbnailChanged();
+ }
+
+public:
+ // void uploadThumbnail(QImage img);
+
+ std::unique_ptr<QIODevice> source;
+ QByteArray data;
+ QString mimetype_;
+ QString mimeClass_;
+ QString originalFilename_;
+ QString blurhash_;
+ QString thumbnailUrl_;
+ QString url_;
+ std::optional<mtx::crypto::EncryptedFile> encryptedFile, thumbnailEncryptedFile;
+
+ QImage thumbnail_;
+
+ QSize dimensions_;
+ uint64_t size_ = 0;
+ uint64_t thumbnailSize_ = 0;
+ uint64_t duration_ = 0;
+ bool encrypt_;
+};
+
class InputBar : public QObject
{
Q_OBJECT
Q_PROPERTY(bool uploading READ uploading NOTIFY uploadingChanged)
Q_PROPERTY(bool containsAtRoom READ containsAtRoom NOTIFY containsAtRoomChanged)
Q_PROPERTY(QString text READ text NOTIFY textChanged)
+ Q_PROPERTY(QVariantList uploads READ uploads NOTIFY uploadsChanged)
public:
explicit InputBar(TimelineModel *parent)
@@ -45,6 +179,8 @@ public:
connect(&typingTimeout_, &QTimer::timeout, this, &InputBar::stopTyping);
}
+ QVariantList uploads() const;
+
public slots:
[[nodiscard]] QString text() const;
QString previousText();
@@ -65,15 +201,22 @@ public slots:
void reaction(const QString &reactedEvent, const QString &reactionKey);
void sticker(CombinedImagePackModel *model, int row);
+ void acceptUploads();
+ void declineUploads();
+
private slots:
void startTyping();
void stopTyping();
+ void finalizeUpload(MediaUpload *upload, QString url);
+ void removeRunUpload(MediaUpload *upload);
+
signals:
void insertText(QString text);
void textChanged(QString newText);
void uploadingChanged(bool value);
void containsAtRoomChanged();
+ void uploadsChanged();
private:
void emote(const QString &body, bool rainbowify);
@@ -85,6 +228,10 @@ private:
const QString &mime,
uint64_t dsize,
const QSize &dimensions,
+ const std::optional<mtx::crypto::EncryptedFile> &thumbnailEncryptedFile,
+ const QString &thumbnailUrl,
+ uint64_t thumbnailSize,
+ const QSize &thumbnailDimensions,
const QString &blurhash);
void file(const QString &filename,
const std::optional<mtx::crypto::EncryptedFile> &encryptedFile,
@@ -95,14 +242,24 @@ private:
const std::optional<mtx::crypto::EncryptedFile> &file,
const QString &url,
const QString &mime,
- uint64_t dsize);
+ uint64_t dsize,
+ uint64_t duration);
void video(const QString &filename,
const std::optional<mtx::crypto::EncryptedFile> &file,
const QString &url,
const QString &mime,
- uint64_t dsize);
+ uint64_t dsize,
+ uint64_t duration,
+ const QSize &dimensions,
+ const std::optional<mtx::crypto::EncryptedFile> &thumbnailEncryptedFile,
+ const QString &thumbnailUrl,
+ uint64_t thumbnailSize,
+ const QSize &thumbnailDimensions,
+ const QString &blurhash);
- void showPreview(const QMimeData &source, const QString &path, const QStringList &formats);
+ void startUploadFromPath(const QString &path);
+ void startUploadFromMimeData(const QMimeData &source, const QString &format);
+ void startUpload(std::unique_ptr<QIODevice> dev, const QString &orgPath, const QString &format);
void setUploading(bool value)
{
if (value != uploading_) {
@@ -121,4 +278,16 @@ private:
int selectionStart = 0, selectionEnd = 0, cursorPosition = 0;
bool uploading_ = false;
bool containsAtRoom_ = false;
+
+ struct DeleteLaterDeleter
+ {
+ void operator()(QObject *p)
+ {
+ if (p)
+ p->deleteLater();
+ }
+ };
+ using UploadHandle = std::unique_ptr<MediaUpload, DeleteLaterDeleter>;
+ std::vector<UploadHandle> unconfirmedUploads;
+ std::vector<UploadHandle> runningUploads;
};
|