summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKonstantinos Sideris <sideris.konstantin@gmail.com>2017-11-29 23:39:35 +0200
committerKonstantinos Sideris <sideris.konstantin@gmail.com>2017-11-29 23:39:35 +0200
commitfdb76bb5c1bdce765479442a70ddca80b867caa6 (patch)
treeb418ea31dbe0f140fc2635584666db4ce36bf732 /src
parentb21942a3e3db3e425155c58483a99bc2789de241 (diff)
Implement file uploads
fixes #24
Diffstat (limited to 'src')
-rw-r--r--src/ChatPage.cc11
-rw-r--r--src/FileItem.cc47
-rw-r--r--src/MatrixClient.cc60
-rw-r--r--src/TextInputWidget.cc35
-rw-r--r--src/TimelineItem.cc33
-rw-r--r--src/TimelineView.cc27
-rw-r--r--src/TimelineViewManager.cc19
7 files changed, 132 insertions, 100 deletions
diff --git a/src/ChatPage.cc b/src/ChatPage.cc
index 82e694a1..5214d49a 100644
--- a/src/ChatPage.cc
+++ b/src/ChatPage.cc
@@ -187,6 +187,10 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
client_->uploadImage(current_room_, filename);
});
+ connect(text_input_, &TextInputWidget::uploadFile, this, [=](QString filename) {
+ client_->uploadFile(current_room_, filename);
+ });
+
connect(client_.data(), &MatrixClient::joinFailed, this, &ChatPage::showNotification);
connect(client_.data(),
&MatrixClient::imageUploaded,
@@ -195,6 +199,13 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
text_input_->hideUploadSpinner();
view_manager_->queueImageMessage(roomid, filename, url);
});
+ connect(client_.data(),
+ &MatrixClient::fileUploaded,
+ this,
+ [=](QString roomid, QString filename, QString url) {
+ text_input_->hideUploadSpinner();
+ view_manager_->queueFileMessage(roomid, filename, url);
+ });
connect(client_.data(),
SIGNAL(roomAvatarRetrieved(const QString &, const QPixmap &)),
diff --git a/src/FileItem.cc b/src/FileItem.cc
index cd934783..96fd9c07 100644
--- a/src/FileItem.cc
+++ b/src/FileItem.cc
@@ -30,25 +30,16 @@
namespace events = matrix::events;
namespace msgs = matrix::events::messages;
-FileItem::FileItem(QSharedPointer<MatrixClient> client,
- const events::MessageEvent<msgs::File> &event,
- QWidget *parent)
- : QWidget(parent)
- , event_{event}
- , client_{client}
+void
+FileItem::init()
{
setMouseTracking(true);
setCursor(Qt::PointingHandCursor);
setAttribute(Qt::WA_Hover, true);
- url_ = event.msgContent().url();
- text_ = event.content().body();
- readableFileSize_ = calculateFileSize(event.msgContent().info().size);
-
icon_.addFile(":/icons/icons/ui/arrow-pointing-down.png");
QList<QString> url_parts = url_.toString().split("mxc://");
-
if (url_parts.size() != 2) {
qDebug() << "Invalid format for image" << url_.toString();
return;
@@ -62,6 +53,20 @@ FileItem::FileItem(QSharedPointer<MatrixClient> client,
}
FileItem::FileItem(QSharedPointer<MatrixClient> client,
+ const events::MessageEvent<msgs::File> &event,
+ QWidget *parent)
+ : QWidget(parent)
+ , url_{event.msgContent().url()}
+ , text_{event.content().body()}
+ , event_{event}
+ , client_{client}
+{
+ readableFileSize_ = calculateFileSize(event.msgContent().info().size);
+
+ init();
+}
+
+FileItem::FileItem(QSharedPointer<MatrixClient> client,
const QString &url,
const QString &filename,
QWidget *parent)
@@ -70,25 +75,9 @@ FileItem::FileItem(QSharedPointer<MatrixClient> client,
, text_{QFileInfo(filename).fileName()}
, client_{client}
{
- setMouseTracking(true);
- setCursor(Qt::PointingHandCursor);
- setAttribute(Qt::WA_Hover, true);
-
- // TODO: calculateFileSize
- /* readableFileSize_ = calculateFileSize(event.msgContent().info().size); */
-
- QList<QString> url_parts = url_.toString().split("mxc://");
-
- icon_.addFile(":/icons/icons/ui/arrow-pointing-down.png");
+ readableFileSize_ = calculateFileSize(QFileInfo(filename).size());
- if (url_parts.size() != 2) {
- qDebug() << "Invalid format for image" << url_.toString();
- return;
- }
-
- QString media_params = url_parts[1];
- url_ = QString("%1/_matrix/media/r0/download/%2")
- .arg(client_.data()->getHomeServer().toString(), media_params);
+ init();
}
QString
diff --git a/src/MatrixClient.cc b/src/MatrixClient.cc
index a171cd09..66630c80 100644
--- a/src/MatrixClient.cc
+++ b/src/MatrixClient.cc
@@ -21,6 +21,7 @@
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
+#include <QMimeDatabase>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QPixmap>
@@ -287,6 +288,9 @@ MatrixClient::sendRoomMessage(matrix::events::MessageEventType ty,
case matrix::events::MessageEventType::Image:
body = {{"msgtype", "m.image"}, {"body", msg}, {"url", url}};
break;
+ case matrix::events::MessageEventType::File:
+ body = {{"msgtype", "m.file"}, {"body", msg}, {"url", url}};
+ break;
default:
qDebug() << "SendRoomMessage: Unknown message type for" << msg;
return;
@@ -756,6 +760,62 @@ MatrixClient::uploadImage(const QString &roomid, const QString &filename)
}
void
+MatrixClient::uploadFile(const QString &roomid, const QString &filename)
+{
+ QUrlQuery query;
+ query.addQueryItem("access_token", token_);
+
+ QUrl endpoint(server_);
+ endpoint.setPath(mediaApiUrl_ + "/upload");
+ endpoint.setQuery(query);
+
+ QFile file(filename);
+ if (!file.open(QIODevice::ReadWrite)) {
+ qDebug() << "Error while reading" << filename;
+ return;
+ }
+
+ QMimeDatabase db;
+ QMimeType mime = db.mimeTypeForFile(filename, QMimeDatabase::MatchContent);
+
+ QNetworkRequest request(QString(endpoint.toEncoded()));
+ request.setHeader(QNetworkRequest::ContentLengthHeader, file.size());
+ request.setHeader(QNetworkRequest::ContentTypeHeader, mime.name());
+
+ auto reply = post(request, file.readAll());
+ connect(reply, &QNetworkReply::finished, this, [this, reply, roomid, filename]() {
+ reply->deleteLater();
+
+ int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+
+ if (status == 0 || status >= 400) {
+ emit syncFailed(reply->errorString());
+ return;
+ }
+
+ auto data = reply->readAll();
+
+ if (data.isEmpty())
+ return;
+
+ auto json = QJsonDocument::fromJson(data);
+
+ if (!json.isObject()) {
+ qDebug() << "Media upload: Response is not a json object.";
+ return;
+ }
+
+ QJsonObject object = json.object();
+ if (!object.contains("content_uri")) {
+ qDebug() << "Media upload: Missing content_uri key";
+ qDebug() << object;
+ return;
+ }
+
+ emit fileUploaded(roomid, filename, object.value("content_uri").toString());
+ });
+}
+void
MatrixClient::joinRoom(const QString &roomIdOrAlias)
{
QUrlQuery query;
diff --git a/src/TextInputWidget.cc b/src/TextInputWidget.cc
index 829784fd..c4d01357 100644
--- a/src/TextInputWidget.cc
+++ b/src/TextInputWidget.cc
@@ -276,30 +276,27 @@ TextInputWidget::command(QString command, QString args)
void
TextInputWidget::openFileSelection()
{
- QStringList supportedFiles;
- supportedFiles << "jpeg"
- << "gif"
- << "png"
- << "bmp"
- << "tiff"
- << "webp";
-
- auto fileName = QFileDialog::getOpenFileName(
- this,
- tr("Select an image"),
- "",
- tr("Image Files (*.bmp *.gif *.jpg *.jpeg *.png *.tiff *.webp)"));
+ QStringList imageExtensions;
+ imageExtensions << "jpeg"
+ << "gif"
+ << "png"
+ << "bmp"
+ << "tiff"
+ << "webp";
+
+ auto fileName =
+ QFileDialog::getOpenFileName(this, tr("Select an file"), "", tr("All Files (*)"));
if (fileName.isEmpty())
return;
- auto imageFormat = QString(QImageReader::imageFormat(fileName));
- if (!supportedFiles.contains(imageFormat)) {
- qDebug() << "Unsupported image format for" << fileName;
- return;
- }
+ auto format = QString(QImageReader::imageFormat(fileName));
+
+ if (imageExtensions.contains(format))
+ emit uploadImage(fileName);
+ else
+ emit uploadFile(fileName);
- emit uploadImage(fileName);
showUploadSpinner();
}
diff --git a/src/TimelineItem.cc b/src/TimelineItem.cc
index b57f5118..7297abc3 100644
--- a/src/TimelineItem.cc
+++ b/src/TimelineItem.cc
@@ -15,20 +15,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <QDateTime>
#include <QFontDatabase>
#include <QRegExp>
#include <QSettings>
#include <QTextEdit>
#include "Avatar.h"
-#include "AvatarProvider.h"
#include "Config.h"
#include "FileItem.h"
#include "ImageItem.h"
#include "Sync.h"
#include "TimelineItem.h"
-#include "TimelineViewManager.h"
static const QRegExp URL_REGEX("((?:https?|ftp)://\\S+)");
static const QString URL_HTML = "<a href=\"\\1\">\\1</a>";
@@ -119,29 +116,15 @@ TimelineItem::TimelineItem(ImageItem *image,
{
init();
- auto displayName = TimelineViewManager::displayName(userid);
- auto timestamp = QDateTime::currentDateTime();
-
- descriptionMsg_ = {"You", userid, " sent an image", descriptiveTime(timestamp)};
-
- generateTimestamp(timestamp);
-
- auto imageLayout = new QHBoxLayout();
- imageLayout->setMargin(0);
- imageLayout->addWidget(image);
- imageLayout->addStretch(1);
-
- if (withSender) {
- generateBody(displayName, "");
- setupAvatarLayout(displayName);
- mainLayout_->addLayout(headerLayout_);
+ setupLocalWidgetLayout<ImageItem>(image, userid, "sent an image", withSender);
+}
- AvatarProvider::resolve(userid, this);
- } else {
- setupSimpleLayout();
- }
+TimelineItem::TimelineItem(FileItem *file, const QString &userid, bool withSender, QWidget *parent)
+ : QWidget{parent}
+{
+ init();
- mainLayout_->addLayout(imageLayout);
+ setupLocalWidgetLayout<FileItem>(file, userid, "sent a file", withSender);
}
/*
@@ -169,7 +152,7 @@ TimelineItem::TimelineItem(ImageItem *image,
generateTimestamp(timestamp);
auto imageLayout = new QHBoxLayout();
- imageLayout->setMargin(0);
+ imageLayout->setContentsMargins(0, 5, 0, 0);
imageLayout->addWidget(image);
imageLayout->addStretch(1);
diff --git a/src/TimelineView.cc b/src/TimelineView.cc
index bdc59af3..346ecc52 100644
--- a/src/TimelineView.cc
+++ b/src/TimelineView.cc
@@ -18,7 +18,6 @@
#include <QApplication>
#include <QDebug>
#include <QFileInfo>
-#include <QSettings>
#include <QTimer>
#include "FileItem.h"
@@ -27,7 +26,6 @@
#include "RoomMessages.h"
#include "ScrollBar.h"
#include "Sync.h"
-#include "TimelineItem.h"
#include "TimelineView.h"
namespace events = matrix::events;
@@ -570,30 +568,6 @@ TimelineView::addUserMessage(matrix::events::MessageEventType ty, const QString
}
void
-TimelineView::addUserMessage(const QString &url, const QString &filename)
-{
- QSettings settings;
- auto user_id = settings.value("auth/user_id").toString();
- auto with_sender = lastSender_ != user_id;
-
- auto image = new ImageItem(client_, url, filename, this);
-
- TimelineItem *view_item = new TimelineItem(image, user_id, with_sender, scroll_widget_);
- scroll_layout_->addWidget(view_item);
-
- lastMessageDirection_ = TimelineDirection::Bottom;
-
- QApplication::processEvents();
-
- lastSender_ = user_id;
-
- int txn_id = client_->incrementTransactionId();
- PendingMessage message(
- matrix::events::MessageEventType::Image, txn_id, url, filename, "", view_item);
- handleNewUserMessage(message);
-}
-
-void
TimelineView::handleNewUserMessage(PendingMessage msg)
{
pending_msgs_.enqueue(msg);
@@ -610,6 +584,7 @@ TimelineView::sendNextPendingMessage()
PendingMessage &m = pending_msgs_.head();
switch (m.ty) {
case matrix::events::MessageEventType::Image:
+ case matrix::events::MessageEventType::File:
client_->sendRoomMessage(
m.ty, m.txn_id, room_id_, QFileInfo(m.filename).fileName(), m.body);
break;
diff --git a/src/TimelineViewManager.cc b/src/TimelineViewManager.cc
index 1f047d7c..daec481b 100644
--- a/src/TimelineViewManager.cc
+++ b/src/TimelineViewManager.cc
@@ -22,6 +22,8 @@
#include <QFileInfo>
#include <QSettings>
+#include "FileItem.h"
+#include "ImageItem.h"
#include "MatrixClient.h"
#include "Sync.h"
#include "TimelineView.h"
@@ -92,7 +94,22 @@ TimelineViewManager::queueImageMessage(const QString &roomid,
auto view = views_[roomid];
- view->addUserMessage(url, filename);
+ view->addUserMessage<ImageItem, matrix::events::MessageEventType::Image>(url, filename);
+}
+
+void
+TimelineViewManager::queueFileMessage(const QString &roomid,
+ const QString &filename,
+ const QString &url)
+{
+ if (!views_.contains(roomid)) {
+ qDebug() << "Cannot send m.file message to a non-managed view";
+ return;
+ }
+
+ auto view = views_[roomid];
+
+ view->addUserMessage<FileItem, matrix::events::MessageEventType::File>(url, filename);
}
void