From 544b62351212188449851b7092cf229091c6f612 Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Mon, 11 Dec 2017 23:00:37 +0200 Subject: [PATCH] Add dialog to create rooms fixes #25 --- CMakeLists.txt | 2 + include/MatrixClient.h | 3 + include/SideBarActions.h | 5 ++ include/dialogs/CreateRoom.h | 44 +++++++++ libs/matrix-structs | 2 +- resources/styles/nheko-dark.qss | 1 + resources/styles/nheko.qss | 1 + src/ChatPage.cc | 7 ++ src/MatrixClient.cc | 43 +++++++++ src/SideBarActions.cc | 27 ++++++ src/dialogs/CreateRoom.cc | 152 ++++++++++++++++++++++++++++++++ 11 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 include/dialogs/CreateRoom.h create mode 100644 src/dialogs/CreateRoom.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index b6affe75..4e71b5f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,6 +141,7 @@ endif() # set(SRC_FILES # Dialogs + src/dialogs/CreateRoom.cc src/dialogs/ImageOverlay.cc src/dialogs/InviteUsers.cc src/dialogs/JoinRoom.cc @@ -219,6 +220,7 @@ include_directories(${LMDB_INCLUDE_DIR}) qt5_wrap_cpp(MOC_HEADERS # Dialogs + include/dialogs/CreateRoom.h include/dialogs/ImageOverlay.h include/dialogs/InviteUsers.h include/dialogs/JoinRoom.h diff --git a/include/MatrixClient.h b/include/MatrixClient.h index ee493da6..2e76061f 100644 --- a/include/MatrixClient.h +++ b/include/MatrixClient.h @@ -61,6 +61,7 @@ public: void removeTypingNotification(const QString &roomid); void readEvent(const QString &room_id, const QString &event_id); void inviteUser(const QString &room_id, const QString &user); + void createRoom(const mtx::requests::CreateRoom &request); QUrl getHomeServer() { return server_; }; int transactionId() { return txn_id_; }; @@ -86,6 +87,7 @@ signals: void loggedOut(); void invitedUser(const QString &room_id, const QString &user); + void roomCreated(const QString &room_id); void loginSuccess(const QString &userid, const QString &homeserver, const QString &token); void registerSuccess(const QString &userid, @@ -115,6 +117,7 @@ signals: void messagesRetrieved(const QString &room_id, const mtx::responses::Messages &msgs); void joinedRoom(const QString &room_id); void leftRoom(const QString &room_id); + void roomCreationFailed(const QString &msg); private: QNetworkReply *makeUploadRequest(const QString &filename); diff --git a/include/SideBarActions.h b/include/SideBarActions.h index 7fbb7e67..f9b9bb1c 100644 --- a/include/SideBarActions.h +++ b/include/SideBarActions.h @@ -8,6 +8,7 @@ #include "FlatButton.h" #include "Menu.h" +#include "dialogs/CreateRoom.h" #include "dialogs/JoinRoom.h" class OverlayModal; @@ -23,6 +24,7 @@ public: signals: void showSettings(); void joinRoom(const QString &room); + void createRoom(const mtx::requests::CreateRoom &request); protected: void resizeEvent(QResizeEvent *event) override; @@ -37,6 +39,9 @@ private: QSharedPointer joinRoomModal_; QSharedPointer joinRoomDialog_; + QSharedPointer createRoomModal_; + QSharedPointer createRoomDialog_; + FlatButton *settingsBtn_; FlatButton *createRoomBtn_; FlatButton *joinRoomBtn_; diff --git a/include/dialogs/CreateRoom.h b/include/dialogs/CreateRoom.h new file mode 100644 index 00000000..96095187 --- /dev/null +++ b/include/dialogs/CreateRoom.h @@ -0,0 +1,44 @@ +#pragma once + +#include + +#include + +class FlatButton; +class TextField; +class QComboBox; +class Toggle; + +namespace dialogs { + +class CreateRoom : public QFrame +{ + Q_OBJECT +public: + CreateRoom(QWidget *parent = nullptr); + +signals: + void closing(bool isCreating, const mtx::requests::CreateRoom &request); + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + void clearFields(); + + QComboBox *visibilityCombo_; + QComboBox *presetCombo_; + + Toggle *directToggle_; + + FlatButton *confirmBtn_; + FlatButton *cancelBtn_; + + TextField *nameInput_; + TextField *topicInput_; + TextField *aliasInput_; + + mtx::requests::CreateRoom request_; +}; + +} // dialogs diff --git a/libs/matrix-structs b/libs/matrix-structs index 9946ed12..d03a370f 160000 --- a/libs/matrix-structs +++ b/libs/matrix-structs @@ -1 +1 @@ -Subproject commit 9946ed125e5cc3b2fb425648679ada615c862be3 +Subproject commit d03a370ffd1bbdd5623afbe9817d1b929bc76cd7 diff --git a/resources/styles/nheko-dark.qss b/resources/styles/nheko-dark.qss index 42ee6740..0fd519ea 100644 --- a/resources/styles/nheko-dark.qss +++ b/resources/styles/nheko-dark.qss @@ -79,6 +79,7 @@ Avatar { dialogs--Logout, dialogs--LeaveRoom, +dialogs--CreateRoom, dialogs--InviteUsers, dialogs--JoinRoom { background-color: #383c4a; diff --git a/resources/styles/nheko.qss b/resources/styles/nheko.qss index 6c592ac8..c55b64fb 100644 --- a/resources/styles/nheko.qss +++ b/resources/styles/nheko.qss @@ -81,6 +81,7 @@ Avatar { dialogs--Logout, dialogs--LeaveRoom, +dialogs--CreateRoom, dialogs--InviteUsers, dialogs--JoinRoom { background-color: white; diff --git a/src/ChatPage.cc b/src/ChatPage.cc index dfae487d..4f03026d 100644 --- a/src/ChatPage.cc +++ b/src/ChatPage.cc @@ -70,6 +70,8 @@ ChatPage::ChatPage(QSharedPointer client, QWidget *parent) sidebarActions_, &SideBarActions::showSettings, this, &ChatPage::showUserSettingsPage); connect( sidebarActions_, &SideBarActions::joinRoom, client_.data(), &MatrixClient::joinRoom); + connect( + sidebarActions_, &SideBarActions::createRoom, client_.data(), &MatrixClient::createRoom); user_info_widget_ = new UserInfoWidget(sideBar_); room_list_ = new RoomList(client, sideBar_); @@ -202,6 +204,8 @@ ChatPage::ChatPage(QSharedPointer client, QWidget *parent) client_->uploadAudio(current_room_, filename); }); + connect( + client_.data(), &MatrixClient::roomCreationFailed, this, &ChatPage::showNotification); connect(client_.data(), &MatrixClient::joinFailed, this, &ChatPage::showNotification); connect(client_.data(), &MatrixClient::imageUploaded, @@ -268,6 +272,9 @@ ChatPage::ChatPage(QSharedPointer client, QWidget *parent) connect(client_.data(), &MatrixClient::invitedUser, this, [=](QString, QString user) { emit showNotification(QString("Invited user %1").arg(user)); }); + connect(client_.data(), &MatrixClient::roomCreated, this, [=](QString room_id) { + emit showNotification(QString("Room %1 created").arg(room_id)); + }); connect(client_.data(), &MatrixClient::leftRoom, this, &ChatPage::removeRoom); showContentTimer_ = new QTimer(this); diff --git a/src/MatrixClient.cc b/src/MatrixClient.cc index b18b6e4a..4634345b 100644 --- a/src/MatrixClient.cc +++ b/src/MatrixClient.cc @@ -890,6 +890,49 @@ MatrixClient::inviteUser(const QString &roomId, const QString &user) emit invitedUser(roomId, user); }); } + +void +MatrixClient::createRoom(const mtx::requests::CreateRoom &create_room_request) +{ + QUrlQuery query; + query.addQueryItem("access_token", token_); + + QUrl endpoint(server_); + endpoint.setPath(clientApiUrl_ + QString("/createRoom")); + endpoint.setQuery(query); + + QNetworkRequest request(endpoint); + request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json"); + + nlohmann::json body = create_room_request; + auto reply = post(request, QString::fromStdString(body.dump()).toUtf8()); + + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + reply->deleteLater(); + + int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + + if (status == 0 || status >= 400) { + auto data = reply->readAll(); + auto response = QJsonDocument::fromJson(data); + auto json = response.object(); + + if (json.contains("error")) + emit roomCreationFailed(json["error"].toString()); + else + qDebug() << reply->errorString(); + + return; + } + + auto data = reply->readAll(); + auto response = QJsonDocument::fromJson(data); + auto room_id = response.object()["room_id"].toString(); + + emit roomCreated(room_id); + }); +} + void MatrixClient::sendTypingNotification(const QString &roomid, int timeoutInMillis) { diff --git a/src/SideBarActions.cc b/src/SideBarActions.cc index f6e99270..c09821ff 100644 --- a/src/SideBarActions.cc +++ b/src/SideBarActions.cc @@ -1,3 +1,4 @@ +#include #include #include "Config.h" @@ -59,6 +60,32 @@ SideBarActions::SideBarActions(QWidget *parent) joinRoomModal_->fadeIn(); }); + connect(createRoomAction_, &QAction::triggered, this, [=]() { + if (createRoomDialog_.isNull()) { + createRoomDialog_ = + QSharedPointer(new dialogs::CreateRoom(this)); + + connect(createRoomDialog_.data(), + &dialogs::CreateRoom::closing, + this, + [=](bool isCreating, const mtx::requests::CreateRoom &request) { + createRoomModal_->fadeOut(); + + if (isCreating) + emit createRoom(request); + }); + } + + if (createRoomModal_.isNull()) { + createRoomModal_ = QSharedPointer( + new OverlayModal(MainWindow::instance(), createRoomDialog_.data())); + createRoomModal_->setDuration(0); + createRoomModal_->setColor(QColor(30, 30, 30, 170)); + } + + createRoomModal_->fadeIn(); + }); + addMenu_->addAction(createRoomAction_); addMenu_->addAction(joinRoomAction_); diff --git a/src/dialogs/CreateRoom.cc b/src/dialogs/CreateRoom.cc new file mode 100644 index 00000000..c46636ab --- /dev/null +++ b/src/dialogs/CreateRoom.cc @@ -0,0 +1,152 @@ +#include +#include +#include +#include + +#include "Config.h" +#include "FlatButton.h" +#include "TextField.h" +#include "Theme.h" +#include "ToggleButton.h" + +#include "dialogs/CreateRoom.h" + +using namespace dialogs; + +CreateRoom::CreateRoom(QWidget *parent) + : QFrame(parent) +{ + setMaximumSize(520, 600); + + auto layout = new QVBoxLayout(this); + layout->setSpacing(30); + layout->setMargin(20); + + auto buttonLayout = new QHBoxLayout(); + buttonLayout->setSpacing(0); + buttonLayout->setMargin(0); + + confirmBtn_ = new FlatButton("CREATE", this); + confirmBtn_->setFontSize(conf::btn::fontSize); + + cancelBtn_ = new FlatButton(tr("CANCEL"), this); + cancelBtn_->setFontSize(conf::btn::fontSize); + + buttonLayout->addStretch(1); + buttonLayout->addWidget(confirmBtn_); + buttonLayout->addWidget(cancelBtn_); + + QFont font; + font.setPixelSize(conf::headerFontSize); + + nameInput_ = new TextField(this); + nameInput_->setLabel(tr("Name")); + + topicInput_ = new TextField(this); + topicInput_->setLabel(tr("Topic")); + + aliasInput_ = new TextField(this); + aliasInput_->setLabel(tr("Alias")); + + auto visibilityLayout = new QHBoxLayout; + visibilityLayout->setContentsMargins(0, 10, 0, 10); + + auto presetLayout = new QHBoxLayout; + presetLayout->setContentsMargins(0, 10, 0, 10); + + auto visibilityLabel = new QLabel(tr("Room visibility"), this); + visibilityCombo_ = new QComboBox(this); + visibilityCombo_->addItem("Private"); + visibilityCombo_->addItem("Public"); + + visibilityLayout->addWidget(visibilityLabel); + visibilityLayout->addWidget(visibilityCombo_, 0, Qt::AlignBottom | Qt::AlignRight); + + auto presetLabel = new QLabel(tr("Room preset"), this); + presetCombo_ = new QComboBox(this); + presetCombo_->addItem("Private Chat"); + presetCombo_->addItem("Public Chat"); + presetCombo_->addItem("Trusted Private Chat"); + + presetLayout->addWidget(presetLabel); + presetLayout->addWidget(presetCombo_, 0, Qt::AlignBottom | Qt::AlignRight); + + auto directLabel_ = new QLabel(tr("Direct Chat"), this); + directToggle_ = new Toggle(this); + directToggle_->setActiveColor(QColor("#38A3D8")); + directToggle_->setInactiveColor(QColor("gray")); + directToggle_->setState(true); + directLabel_->setStyleSheet("font-size: 15px;"); + + auto directLayout = new QHBoxLayout; + directLayout->setContentsMargins(0, 10, 0, 10); + directLayout->addWidget(directLabel_); + directLayout->addWidget(directToggle_, 0, Qt::AlignBottom | Qt::AlignRight); + + layout->addWidget(nameInput_); + layout->addWidget(topicInput_); + layout->addWidget(aliasInput_); + layout->addLayout(visibilityLayout); + layout->addLayout(presetLayout); + layout->addLayout(directLayout); + layout->addLayout(buttonLayout); + + connect(confirmBtn_, &QPushButton::clicked, this, [=]() { + request_.name = nameInput_->text().toStdString(); + request_.topic = topicInput_->text().toStdString(); + request_.room_alias_name = aliasInput_->text().toStdString(); + + emit closing(true, request_); + + clearFields(); + }); + + connect(cancelBtn_, &QPushButton::clicked, this, [=]() { + emit closing(false, request_); + + clearFields(); + }); + + connect(visibilityCombo_, + static_cast(&QComboBox::activated), + [=](const QString &text) { + if (text == "Private") { + request_.visibility = mtx::requests::Visibility::Private; + } else { + request_.visibility = mtx::requests::Visibility::Public; + } + }); + + connect(presetCombo_, + static_cast(&QComboBox::activated), + [=](const QString &text) { + if (text == "Private Chat") { + request_.preset = mtx::requests::Preset::PrivateChat; + } else if (text == "Public Chat") { + request_.preset = mtx::requests::Preset::PublicChat; + } else { + request_.preset = mtx::requests::Preset::TrustedPrivateChat; + } + }); + + connect(directToggle_, &Toggle::toggled, this, [=](bool isDisabled) { + request_.is_direct = !isDisabled; + }); +} + +void +CreateRoom::clearFields() +{ + nameInput_->clear(); + topicInput_->clear(); + aliasInput_->clear(); +} + +void +CreateRoom::paintEvent(QPaintEvent *) +{ + QStyleOption opt; + opt.init(this); + QPainter p(this); + style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); +}