summary refs log tree commit diff
path: root/src/timeline/InputBar.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/timeline/InputBar.h')
-rw-r--r--src/timeline/InputBar.h175
1 files changed, 172 insertions, 3 deletions
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; };