Skip to content
Snippets Groups Projects
Commit 5573548f authored by Konstantinos Sideris's avatar Konstantinos Sideris
Browse files

Allow audio clip uploads

parent 78353a29
No related branches found
No related tags found
No related merge requests found
Showing
with 165 additions and 56 deletions
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#pragma once #pragma once
#include <QFileInfo>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QUrl> #include <QUrl>
...@@ -43,6 +44,7 @@ public: ...@@ -43,6 +44,7 @@ public:
int txnId, int txnId,
const QString &roomid, const QString &roomid,
const QString &msg, const QString &msg,
const QFileInfo &info,
const QString &url = "") noexcept; const QString &url = "") noexcept;
void login(const QString &username, const QString &password) noexcept; void login(const QString &username, const QString &password) noexcept;
void registerUser(const QString &username, void registerUser(const QString &username,
...@@ -57,6 +59,7 @@ public: ...@@ -57,6 +59,7 @@ public:
void messages(const QString &room_id, const QString &from_token, int limit = 30) noexcept; void messages(const QString &room_id, const QString &from_token, int limit = 30) noexcept;
void uploadImage(const QString &roomid, const QString &filename); void uploadImage(const QString &roomid, const QString &filename);
void uploadFile(const QString &roomid, const QString &filename); void uploadFile(const QString &roomid, const QString &filename);
void uploadAudio(const QString &roomid, const QString &filename);
void joinRoom(const QString &roomIdOrAlias); void joinRoom(const QString &roomIdOrAlias);
void leaveRoom(const QString &roomId); void leaveRoom(const QString &roomId);
void sendTypingNotification(const QString &roomid, int timeoutInMillis = 20000); void sendTypingNotification(const QString &roomid, int timeoutInMillis = 20000);
...@@ -94,6 +97,7 @@ signals: ...@@ -94,6 +97,7 @@ signals:
void versionSuccess(); void versionSuccess();
void imageUploaded(const QString &roomid, const QString &filename, const QString &url); void imageUploaded(const QString &roomid, const QString &filename, const QString &url);
void fileUploaded(const QString &roomid, const QString &filename, const QString &url); void fileUploaded(const QString &roomid, const QString &filename, const QString &url);
void audioUploaded(const QString &roomid, const QString &filename, const QString &url);
void roomAvatarRetrieved(const QString &roomid, const QPixmap &img); void roomAvatarRetrieved(const QString &roomid, const QPixmap &img);
void userAvatarRetrieved(const QString &userId, const QImage &img); void userAvatarRetrieved(const QString &userId, const QImage &img);
...@@ -116,6 +120,8 @@ signals: ...@@ -116,6 +120,8 @@ signals:
void leftRoom(const QString &room_id); void leftRoom(const QString &room_id);
private: private:
QNetworkReply *makeUploadRequest(const QString &filename);
// Client API prefix. // Client API prefix.
QString clientApiUrl_; QString clientApiUrl_;
......
...@@ -85,8 +85,11 @@ private slots: ...@@ -85,8 +85,11 @@ private slots:
signals: signals:
void sendTextMessage(QString msg); void sendTextMessage(QString msg);
void sendEmoteMessage(QString msg); void sendEmoteMessage(QString msg);
void uploadImage(QString filename); void uploadImage(QString filename);
void uploadFile(QString filename); void uploadFile(QString filename);
void uploadAudio(QString filename);
void sendJoinRoomRequest(const QString &room); void sendJoinRoomRequest(const QString &room);
void startedTyping(); void startedTyping();
......
...@@ -55,7 +55,7 @@ struct ThumbnailInfo ...@@ -55,7 +55,7 @@ struct ThumbnailInfo
{ {
int h; int h;
int w; int w;
int size; int size = 0;
QString mimetype; QString mimetype;
}; };
......
...@@ -27,7 +27,7 @@ namespace messages { ...@@ -27,7 +27,7 @@ namespace messages {
struct AudioInfo struct AudioInfo
{ {
uint64_t duration; uint64_t duration;
int size; int size = 0;
QString mimetype; QString mimetype;
}; };
......
...@@ -27,7 +27,7 @@ namespace events { ...@@ -27,7 +27,7 @@ namespace events {
namespace messages { namespace messages {
struct FileInfo struct FileInfo
{ {
int size; int size = 0;
QString mimetype; QString mimetype;
QString thumbnail_url; QString thumbnail_url;
......
...@@ -29,7 +29,7 @@ struct ImageInfo ...@@ -29,7 +29,7 @@ struct ImageInfo
{ {
int h; int h;
int w; int w;
int size; int size = 0;
QString mimetype; QString mimetype;
QString thumbnail_url; QString thumbnail_url;
......
...@@ -29,7 +29,7 @@ struct VideoInfo ...@@ -29,7 +29,7 @@ struct VideoInfo
{ {
int h; int h;
int w; int w;
int size; int size = 0;
int duration; int duration;
QString mimetype; QString mimetype;
......
...@@ -68,6 +68,7 @@ public slots: ...@@ -68,6 +68,7 @@ public slots:
void queueEmoteMessage(const QString &msg); void queueEmoteMessage(const QString &msg);
void queueImageMessage(const QString &roomid, const QString &filename, const QString &url); void queueImageMessage(const QString &roomid, const QString &filename, const QString &url);
void queueFileMessage(const QString &roomid, const QString &filename, const QString &url); void queueFileMessage(const QString &roomid, const QString &filename, const QString &url);
void queueAudioMessage(const QString &roomid, const QString &filename, const QString &url);
private slots: private slots:
void messageSent(const QString &eventid, const QString &roomid, int txnid); void messageSent(const QString &eventid, const QString &roomid, int txnid);
......
...@@ -28,6 +28,12 @@ FileItem { ...@@ -28,6 +28,12 @@ FileItem {
qproperty-iconColor: #caccd1; qproperty-iconColor: #caccd1;
} }
AudioItem {
qproperty-textColor: #caccd1;
qproperty-backgroundColor: #414A59;
qproperty-iconColor: #caccd1;
}
RaisedButton { RaisedButton {
qproperty-foregroundColor: #caccd1; qproperty-foregroundColor: #caccd1;
qproperty-backgroundColor: #333; qproperty-backgroundColor: #333;
......
...@@ -27,6 +27,12 @@ FileItem { ...@@ -27,6 +27,12 @@ FileItem {
qproperty-iconColor: white; qproperty-iconColor: white;
} }
AudioItem {
qproperty-textColor: #333;
qproperty-backgroundColor: #f2f2f2;
qproperty-iconColor: white;
}
RaisedButton { RaisedButton {
qproperty-foregroundColor: white; qproperty-foregroundColor: white;
} }
......
...@@ -25,6 +25,12 @@ FileItem { ...@@ -25,6 +25,12 @@ FileItem {
qproperty-iconColor: palette(window); qproperty-iconColor: palette(window);
} }
AudioItem {
qproperty-textColor: palette(text);
qproperty-backgroundColor: palette(base);
qproperty-iconColor: palette(window);
}
RaisedButton { RaisedButton {
qproperty-foregroundColor: palette(light); qproperty-foregroundColor: palette(light);
} }
......
...@@ -192,6 +192,10 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent) ...@@ -192,6 +192,10 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
client_->uploadFile(current_room_, filename); client_->uploadFile(current_room_, filename);
}); });
connect(text_input_, &TextInputWidget::uploadAudio, this, [=](QString filename) {
client_->uploadAudio(current_room_, filename);
});
connect(client_.data(), &MatrixClient::joinFailed, this, &ChatPage::showNotification); connect(client_.data(), &MatrixClient::joinFailed, this, &ChatPage::showNotification);
connect(client_.data(), connect(client_.data(),
&MatrixClient::imageUploaded, &MatrixClient::imageUploaded,
...@@ -207,6 +211,13 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent) ...@@ -207,6 +211,13 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
text_input_->hideUploadSpinner(); text_input_->hideUploadSpinner();
view_manager_->queueFileMessage(roomid, filename, url); view_manager_->queueFileMessage(roomid, filename, url);
}); });
connect(client_.data(),
&MatrixClient::audioUploaded,
this,
[=](QString roomid, QString filename, QString url) {
text_input_->hideUploadSpinner();
view_manager_->queueAudioMessage(roomid, filename, url);
});
connect(client_.data(), connect(client_.data(),
SIGNAL(roomAvatarRetrieved(const QString &, const QPixmap &)), SIGNAL(roomAvatarRetrieved(const QString &, const QPixmap &)),
......
...@@ -265,6 +265,7 @@ MatrixClient::sendRoomMessage(matrix::events::MessageEventType ty, ...@@ -265,6 +265,7 @@ MatrixClient::sendRoomMessage(matrix::events::MessageEventType ty,
int txnId, int txnId,
const QString &roomid, const QString &roomid,
const QString &msg, const QString &msg,
const QFileInfo &fileinfo,
const QString &url) noexcept const QString &url) noexcept
{ {
QUrlQuery query; QUrlQuery query;
...@@ -276,7 +277,13 @@ MatrixClient::sendRoomMessage(matrix::events::MessageEventType ty, ...@@ -276,7 +277,13 @@ MatrixClient::sendRoomMessage(matrix::events::MessageEventType ty,
endpoint.setQuery(query); endpoint.setQuery(query);
QString msgType(""); QString msgType("");
QMimeDatabase db;
QMimeType mime =
db.mimeTypeForFile(fileinfo.absoluteFilePath(), QMimeDatabase::MatchContent);
QJsonObject body; QJsonObject body;
QJsonObject info = {{"size", fileinfo.size()}, {"mimetype", mime.name()}};
switch (ty) { switch (ty) {
case matrix::events::MessageEventType::Text: case matrix::events::MessageEventType::Text:
...@@ -286,10 +293,13 @@ MatrixClient::sendRoomMessage(matrix::events::MessageEventType ty, ...@@ -286,10 +293,13 @@ MatrixClient::sendRoomMessage(matrix::events::MessageEventType ty,
body = {{"msgtype", "m.emote"}, {"body", msg}}; body = {{"msgtype", "m.emote"}, {"body", msg}};
break; break;
case matrix::events::MessageEventType::Image: case matrix::events::MessageEventType::Image:
body = {{"msgtype", "m.image"}, {"body", msg}, {"url", url}}; body = {{"msgtype", "m.image"}, {"body", msg}, {"url", url}, {"info", info}};
break; break;
case matrix::events::MessageEventType::File: case matrix::events::MessageEventType::File:
body = {{"msgtype", "m.file"}, {"body", msg}, {"url", url}}; body = {{"msgtype", "m.file"}, {"body", msg}, {"url", url}, {"info", info}};
break;
case matrix::events::MessageEventType::Audio:
body = {{"msgtype", "m.audio"}, {"body", msg}, {"url", url}, {"info", info}};
break; break;
default: default:
qDebug() << "SendRoomMessage: Unknown message type for" << msg; qDebug() << "SendRoomMessage: Unknown message type for" << msg;
...@@ -706,26 +716,11 @@ MatrixClient::messages(const QString &roomid, const QString &from_token, int lim ...@@ -706,26 +716,11 @@ MatrixClient::messages(const QString &roomid, const QString &from_token, int lim
void void
MatrixClient::uploadImage(const QString &roomid, const QString &filename) MatrixClient::uploadImage(const QString &roomid, const QString &filename)
{ {
QUrlQuery query; auto reply = makeUploadRequest(filename);
query.addQueryItem("access_token", token_);
QUrl endpoint(server_); if (reply == nullptr)
endpoint.setPath(mediaApiUrl_ + "/upload");
endpoint.setQuery(query);
QFile file(filename);
if (!file.open(QIODevice::ReadWrite)) {
qDebug() << "Error while reading" << filename;
return; return;
}
auto imgFormat = QString(QImageReader::imageFormat(filename));
QNetworkRequest request(QString(endpoint.toEncoded()));
request.setHeader(QNetworkRequest::ContentLengthHeader, file.size());
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("image/%1").arg(imgFormat));
auto reply = post(request, file.readAll());
connect(reply, &QNetworkReply::finished, this, [this, reply, roomid, filename]() { connect(reply, &QNetworkReply::finished, this, [this, reply, roomid, filename]() {
reply->deleteLater(); reply->deleteLater();
...@@ -762,27 +757,46 @@ MatrixClient::uploadImage(const QString &roomid, const QString &filename) ...@@ -762,27 +757,46 @@ MatrixClient::uploadImage(const QString &roomid, const QString &filename)
void void
MatrixClient::uploadFile(const QString &roomid, const QString &filename) MatrixClient::uploadFile(const QString &roomid, const QString &filename)
{ {
QUrlQuery query; auto reply = makeUploadRequest(filename);
query.addQueryItem("access_token", token_);
QUrl endpoint(server_); connect(reply, &QNetworkReply::finished, this, [this, reply, roomid, filename]() {
endpoint.setPath(mediaApiUrl_ + "/upload"); reply->deleteLater();
endpoint.setQuery(query);
QFile file(filename); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (!file.open(QIODevice::ReadWrite)) {
qDebug() << "Error while reading" << filename;
return;
}
QMimeDatabase db; if (status == 0 || status >= 400) {
QMimeType mime = db.mimeTypeForFile(filename, QMimeDatabase::MatchContent); emit syncFailed(reply->errorString());
return;
}
QNetworkRequest request(QString(endpoint.toEncoded())); auto data = reply->readAll();
request.setHeader(QNetworkRequest::ContentLengthHeader, file.size());
request.setHeader(QNetworkRequest::ContentTypeHeader, mime.name()); 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::uploadAudio(const QString &roomid, const QString &filename)
{
auto reply = makeUploadRequest(filename);
auto reply = post(request, file.readAll());
connect(reply, &QNetworkReply::finished, this, [this, reply, roomid, filename]() { connect(reply, &QNetworkReply::finished, this, [this, reply, roomid, filename]() {
reply->deleteLater(); reply->deleteLater();
...@@ -812,9 +826,10 @@ MatrixClient::uploadFile(const QString &roomid, const QString &filename) ...@@ -812,9 +826,10 @@ MatrixClient::uploadFile(const QString &roomid, const QString &filename)
return; return;
} }
emit fileUploaded(roomid, filename, object.value("content_uri").toString()); emit audioUploaded(roomid, filename, object.value("content_uri").toString());
}); });
} }
void void
MatrixClient::joinRoom(const QString &roomIdOrAlias) MatrixClient::joinRoom(const QString &roomIdOrAlias)
{ {
...@@ -961,3 +976,31 @@ MatrixClient::readEvent(const QString &room_id, const QString &event_id) ...@@ -961,3 +976,31 @@ MatrixClient::readEvent(const QString &room_id, const QString &event_id)
} }
}); });
} }
QNetworkReply *
MatrixClient::makeUploadRequest(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 nullptr;
}
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());
return reply;
}
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include <QFile> #include <QFile>
#include <QFileDialog> #include <QFileDialog>
#include <QImageReader> #include <QImageReader>
#include <QMimeDatabase>
#include <QMimeType>
#include <QPainter> #include <QPainter>
#include <QStyleOption> #include <QStyleOption>
...@@ -276,24 +278,21 @@ TextInputWidget::command(QString command, QString args) ...@@ -276,24 +278,21 @@ TextInputWidget::command(QString command, QString args)
void void
TextInputWidget::openFileSelection() TextInputWidget::openFileSelection()
{ {
QStringList imageExtensions; const auto fileName =
imageExtensions << "jpeg" QFileDialog::getOpenFileName(this, tr("Select a file"), "", tr("All Files (*)"));
<< "gif"
<< "png"
<< "bmp"
<< "tiff"
<< "webp";
auto fileName =
QFileDialog::getOpenFileName(this, tr("Select an file"), "", tr("All Files (*)"));
if (fileName.isEmpty()) if (fileName.isEmpty())
return; return;
auto format = QString(QImageReader::imageFormat(fileName)); QMimeDatabase db;
QMimeType mime = db.mimeTypeForFile(fileName, QMimeDatabase::MatchContent);
const auto format = mime.name().split("/")[0];
if (imageExtensions.contains(format)) if (format == "image")
emit uploadImage(fileName); emit uploadImage(fileName);
else if (format == "audio")
emit uploadAudio(fileName);
else else
emit uploadFile(fileName); emit uploadFile(fileName);
......
...@@ -436,13 +436,19 @@ TimelineView::sendNextPendingMessage() ...@@ -436,13 +436,19 @@ TimelineView::sendNextPendingMessage()
PendingMessage &m = pending_msgs_.head(); PendingMessage &m = pending_msgs_.head();
switch (m.ty) { switch (m.ty) {
case matrix::events::MessageEventType::Audio:
case matrix::events::MessageEventType::Image: case matrix::events::MessageEventType::Image:
case matrix::events::MessageEventType::File: case matrix::events::MessageEventType::File:
client_->sendRoomMessage( // FIXME: Improve the API
m.ty, m.txn_id, room_id_, QFileInfo(m.filename).fileName(), m.body); client_->sendRoomMessage(m.ty,
m.txn_id,
room_id_,
QFileInfo(m.filename).fileName(),
QFileInfo(m.filename),
m.body);
break; break;
default: default:
client_->sendRoomMessage(m.ty, m.txn_id, room_id_, m.body); client_->sendRoomMessage(m.ty, m.txn_id, room_id_, m.body, QFileInfo());
break; break;
} }
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "timeline/TimelineView.h" #include "timeline/TimelineView.h"
#include "timeline/TimelineViewManager.h" #include "timeline/TimelineViewManager.h"
#include "timeline/widgets/AudioItem.h"
#include "timeline/widgets/FileItem.h" #include "timeline/widgets/FileItem.h"
#include "timeline/widgets/ImageItem.h" #include "timeline/widgets/ImageItem.h"
...@@ -113,6 +114,21 @@ TimelineViewManager::queueFileMessage(const QString &roomid, ...@@ -113,6 +114,21 @@ TimelineViewManager::queueFileMessage(const QString &roomid,
view->addUserMessage<FileItem, matrix::events::MessageEventType::File>(url, filename); view->addUserMessage<FileItem, matrix::events::MessageEventType::File>(url, filename);
} }
void
TimelineViewManager::queueAudioMessage(const QString &roomid,
const QString &filename,
const QString &url)
{
if (!views_.contains(roomid)) {
qDebug() << "Cannot send m.audio message to a non-managed view";
return;
}
auto view = views_[roomid];
view->addUserMessage<AudioItem, matrix::events::MessageEventType::Audio>(url, filename);
}
void void
TimelineViewManager::clearAll() TimelineViewManager::clearAll()
{ {
......
...@@ -107,6 +107,9 @@ AudioItem::AudioItem(QSharedPointer<MatrixClient> client, ...@@ -107,6 +107,9 @@ AudioItem::AudioItem(QSharedPointer<MatrixClient> client,
QString QString
AudioItem::calculateFileSize(int nbytes) const AudioItem::calculateFileSize(int nbytes) const
{ {
if (nbytes == 0)
return QString("");
if (nbytes < 1024) if (nbytes < 1024)
return QString("%1 B").arg(nbytes); return QString("%1 B").arg(nbytes);
......
...@@ -94,6 +94,9 @@ FileItem::FileItem(QSharedPointer<MatrixClient> client, ...@@ -94,6 +94,9 @@ FileItem::FileItem(QSharedPointer<MatrixClient> client,
QString QString
FileItem::calculateFileSize(int nbytes) const FileItem::calculateFileSize(int nbytes) const
{ {
if (nbytes == 0)
return QString("");
if (nbytes < 1024) if (nbytes < 1024)
return QString("%1 B").arg(nbytes); return QString("%1 B").arg(nbytes);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment