Port PlaceCall dialog to Qml

This commit is contained in:
trilene 2020-12-18 12:49:24 -05:00 committed by Nicolas Werner
parent 459c59901e
commit 07ac7b7e85
10 changed files with 131 additions and 227 deletions

View file

@ -253,7 +253,6 @@ set(SRC_FILES
src/dialogs/LeaveRoom.cpp src/dialogs/LeaveRoom.cpp
src/dialogs/Logout.cpp src/dialogs/Logout.cpp
src/dialogs/MemberList.cpp src/dialogs/MemberList.cpp
src/dialogs/PlaceCall.cpp
src/dialogs/PreviewUploadOverlay.cpp src/dialogs/PreviewUploadOverlay.cpp
src/dialogs/ReCaptcha.cpp src/dialogs/ReCaptcha.cpp
src/dialogs/ReadReceipts.cpp src/dialogs/ReadReceipts.cpp
@ -471,7 +470,6 @@ qt5_wrap_cpp(MOC_HEADERS
src/dialogs/LeaveRoom.h src/dialogs/LeaveRoom.h
src/dialogs/Logout.h src/dialogs/Logout.h
src/dialogs/MemberList.h src/dialogs/MemberList.h
src/dialogs/PlaceCall.h
src/dialogs/PreviewUploadOverlay.h src/dialogs/PreviewUploadOverlay.h
src/dialogs/RawMessage.h src/dialogs/RawMessage.h
src/dialogs/ReCaptcha.h src/dialogs/ReCaptcha.h

View file

@ -3,6 +3,7 @@ import QtQuick.Controls 2.3
import QtQuick.Layouts 1.2 import QtQuick.Layouts 1.2
import QtQuick.Window 2.2 import QtQuick.Window 2.2
import im.nheko 1.0 import im.nheko 1.0
import "./voip"
Rectangle { Rectangle {
color: colors.window color: colors.window
@ -10,6 +11,13 @@ Rectangle {
Layout.preferredHeight: textInput.height Layout.preferredHeight: textInput.height
Layout.minimumHeight: 40 Layout.minimumHeight: 40
Component {
id: placeCallDialog
PlaceCall {
}
}
RowLayout { RowLayout {
id: inputBar id: inputBar
@ -28,7 +36,20 @@ Rectangle {
Layout.topMargin: 8 Layout.topMargin: 8
Layout.bottomMargin: 8 Layout.bottomMargin: 8
Layout.leftMargin: 16 Layout.leftMargin: 16
onClicked: TimelineManager.timeline.input.callButton() onClicked: {
if (TimelineManager.timeline) {
if (CallManager.haveCallInvite) {
return;
}
else if (CallManager.isOnCall) {
CallManager.hangUp();
}
else {
var dialog = placeCallDialog.createObject(timelineRoot);
dialog.show();
}
}
}
} }
ImageButton { ImageButton {

View file

@ -0,0 +1,107 @@
import QtQuick 2.3
import QtQuick.Controls 2.3
import QtQuick.Dialogs 1.3
import QtQuick.Layouts 1.2
import im.nheko 1.0
import "../"
ApplicationWindow {
flags: Qt.Dialog
modality: Qt.ApplicationModal
palette: colors
width: columnLayout.implicitWidth
height: columnLayout.implicitHeight
MessageDialog {
id: warningDialog
icon: StandardIcon.Warning
}
ColumnLayout {
id: columnLayout
spacing: 16
RowLayout {
Layout.topMargin: 16
Layout.leftMargin: 8
Label {
font.pointSize: fontMetrics.font.pointSize * 1.1
text: "Place a call to " + TimelineManager.timeline.roomName + "?"
}
Item {
Layout.fillWidth: true
}
}
RowLayout {
id: rowLayout
Layout.leftMargin: 8
Layout.rightMargin: 8
Layout.bottomMargin: 16
spacing: 16
function validateMic() {
if (CallManager.mics.length == 0) {
warningDialog.text = "No microphone found.";
warningDialog.open();
return false;
}
else if (!CallManager.mics.includes(Settings.microphone)) {
warningDialog.text = "Unknown microphone: " + Settings.microphone;
warningDialog.open();
return false;
}
return true;
}
Avatar {
width: avatarSize
height: avatarSize
url: TimelineManager.timeline.roomAvatarUrl.replace("mxc://", "image://MxcImage/")
displayName: TimelineManager.timeline.roomName
}
Button {
text: qsTr("Voice")
icon.source: "qrc:/icons/icons/ui/place-call.png"
onClicked: {
if (rowLayout.validateMic()) {
CallManager.sendInvite(TimelineManager.timeline.roomId(), false);
close();
}
}
}
Button {
visible: CallManager.cameras.length > 0
text: qsTr("Video")
icon.source: "qrc:/icons/icons/ui/video-call.png"
onClicked: {
if (rowLayout.validateMic()) {
if (!CallManager.cameras.includes(Settings.camera)) {
warningDialog.text = "Unknown camera: " + Settings.camera;
warningDialog.open();
return;
}
CallManager.sendInvite(TimelineManager.timeline.roomId(), true);
close();
}
}
}
Button {
palette: colors
text: qsTr("Cancel")
onClicked: {
close();
}
}
}
}
}

View file

@ -159,6 +159,7 @@
<file>qml/device-verification/Success.qml</file> <file>qml/device-verification/Success.qml</file>
<file>qml/voip/ActiveCallBar.qml</file> <file>qml/voip/ActiveCallBar.qml</file>
<file>qml/voip/CallInviteBar.qml</file> <file>qml/voip/CallInviteBar.qml</file>
<file>qml/voip/PlaceCall.qml</file>
<file>qml/voip/VideoCall.qml</file> <file>qml/voip/VideoCall.qml</file>
</qresource> </qresource>
<qresource prefix="/media"> <qresource prefix="/media">

View file

@ -37,7 +37,6 @@ class CallManager : public QObject
public: public:
CallManager(QObject *); CallManager(QObject *);
void sendInvite(const QString &roomid, bool isVideo);
bool haveCallInvite() const { return haveCallInvite_; } bool haveCallInvite() const { return haveCallInvite_; }
bool isOnCall() const { return session_.state() != webrtc::State::DISCONNECTED; } bool isOnCall() const { return session_.state() != webrtc::State::DISCONNECTED; }
bool isVideo() const { return isVideo_; } bool isVideo() const { return isVideo_; }
@ -52,6 +51,7 @@ public:
void refreshTurnServer(); void refreshTurnServer();
public slots: public slots:
void sendInvite(const QString &roomid, bool isVideo);
void syncEvent(const mtx::events::collections::TimelineEvents &event); void syncEvent(const mtx::events::collections::TimelineEvents &event);
void toggleMicMute(); void toggleMicMute();
void toggleCameraView() { session_.toggleCameraView(); } void toggleCameraView() { session_.toggleCameraView(); }

View file

@ -47,7 +47,6 @@
#include "notifications/Manager.h" #include "notifications/Manager.h"
#include "dialogs/PlaceCall.h"
#include "dialogs/ReadReceipts.h" #include "dialogs/ReadReceipts.h"
#include "popups/UserMentions.h" #include "popups/UserMentions.h"
#include "timeline/TimelineViewManager.h" #include "timeline/TimelineViewManager.h"

View file

@ -1,131 +0,0 @@
#include <QComboBox>
#include <QLabel>
#include <QPushButton>
#include <QString>
#include <QVBoxLayout>
#include "ChatPage.h"
#include "Config.h"
#include "UserSettingsPage.h"
#include "Utils.h"
#include "WebRTCSession.h"
#include "dialogs/PlaceCall.h"
#include "ui/Avatar.h"
namespace dialogs {
PlaceCall::PlaceCall(const QString &callee,
const QString &displayName,
const QString &roomName,
const QString &avatarUrl,
QSharedPointer<UserSettings> settings,
QWidget *parent)
: QWidget(parent)
{
std::string errorMessage;
WebRTCSession *session = &WebRTCSession::instance();
if (!session->havePlugins(false, &errorMessage)) {
emit ChatPage::instance()->showNotification(QString::fromStdString(errorMessage));
emit close();
return;
}
session->refreshDevices();
microphones_ = session->getDeviceNames(false, settings->microphone().toStdString());
if (microphones_.empty()) {
emit ChatPage::instance()->showNotification(tr("No microphone found."));
emit close();
return;
}
cameras_ = session->getDeviceNames(true, settings->camera().toStdString());
setAutoFillBackground(true);
setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
setWindowModality(Qt::WindowModal);
setAttribute(Qt::WA_DeleteOnClose, true);
auto layout = new QVBoxLayout(this);
layout->setSpacing(conf::modals::WIDGET_SPACING);
layout->setMargin(conf::modals::WIDGET_MARGIN);
auto buttonLayout = new QHBoxLayout;
buttonLayout->setSpacing(15);
buttonLayout->setMargin(0);
QFont f;
f.setPointSizeF(f.pointSizeF());
auto avatar = new Avatar(this, QFontMetrics(f).height() * 3);
if (!avatarUrl.isEmpty())
avatar->setImage(avatarUrl);
else
avatar->setLetter(utils::firstChar(roomName));
voiceBtn_ = new QPushButton(tr("Voice"), this);
voiceBtn_->setIcon(QIcon(":/icons/icons/ui/place-call.png"));
voiceBtn_->setIconSize(QSize(iconSize_, iconSize_));
voiceBtn_->setDefault(true);
if (!cameras_.empty()) {
videoBtn_ = new QPushButton(tr("Video"), this);
videoBtn_->setIcon(QIcon(":/icons/icons/ui/video-call.png"));
videoBtn_->setIconSize(QSize(iconSize_, iconSize_));
}
cancelBtn_ = new QPushButton(tr("Cancel"), this);
buttonLayout->addWidget(avatar);
buttonLayout->addStretch();
buttonLayout->addWidget(voiceBtn_);
if (videoBtn_)
buttonLayout->addWidget(videoBtn_);
buttonLayout->addWidget(cancelBtn_);
QString name = displayName.isEmpty() ? callee : displayName;
QLabel *label = new QLabel(tr("Place a call to ") + name + "?", this);
microphoneCombo_ = new QComboBox(this);
for (const auto &m : microphones_)
microphoneCombo_->addItem(QIcon(":/icons/icons/ui/microphone-unmute.png"),
QString::fromStdString(m));
if (videoBtn_) {
cameraCombo_ = new QComboBox(this);
for (const auto &c : cameras_)
cameraCombo_->addItem(QIcon(":/icons/icons/ui/video-call.png"),
QString::fromStdString(c));
}
layout->addWidget(label);
layout->addLayout(buttonLayout);
layout->addStretch();
layout->addWidget(microphoneCombo_);
if (videoBtn_)
layout->addWidget(cameraCombo_);
connect(voiceBtn_, &QPushButton::clicked, this, [this, settings]() {
settings->setMicrophone(
QString::fromStdString(microphones_[microphoneCombo_->currentIndex()]));
emit voice();
emit close();
});
if (videoBtn_)
connect(videoBtn_, &QPushButton::clicked, this, [this, settings, session]() {
std::string error;
if (!session->havePlugins(true, &error)) {
emit ChatPage::instance()->showNotification(
QString::fromStdString(error));
emit close();
return;
}
settings->setMicrophone(
QString::fromStdString(microphones_[microphoneCombo_->currentIndex()]));
settings->setCamera(
QString::fromStdString(cameras_[cameraCombo_->currentIndex()]));
emit video();
emit close();
});
connect(cancelBtn_, &QPushButton::clicked, this, [this]() {
emit cancel();
emit close();
});
}
}

View file

@ -1,44 +0,0 @@
#pragma once
#include <string>
#include <vector>
#include <QSharedPointer>
#include <QWidget>
class QComboBox;
class QPushButton;
class QString;
class UserSettings;
namespace dialogs {
class PlaceCall : public QWidget
{
Q_OBJECT
public:
PlaceCall(const QString &callee,
const QString &displayName,
const QString &roomName,
const QString &avatarUrl,
QSharedPointer<UserSettings> settings,
QWidget *parent = nullptr);
signals:
void voice();
void video();
void cancel();
private:
const int iconSize_ = 18;
QPushButton *voiceBtn_ = nullptr;
QPushButton *videoBtn_ = nullptr;
QPushButton *cancelBtn_ = nullptr;
QComboBox *microphoneCombo_ = nullptr;
QComboBox *cameraCombo_ = nullptr;
std::vector<std::string> microphones_;
std::vector<std::string> cameras_;
};
}

View file

@ -13,7 +13,6 @@
#include <mtx/responses/media.hpp> #include <mtx/responses/media.hpp>
#include "Cache.h" #include "Cache.h"
#include "CallManager.h"
#include "ChatPage.h" #include "ChatPage.h"
#include "CompletionProxyModel.h" #include "CompletionProxyModel.h"
#include "Logging.h" #include "Logging.h"
@ -25,7 +24,6 @@
#include "UserSettingsPage.h" #include "UserSettingsPage.h"
#include "UsersModel.h" #include "UsersModel.h"
#include "Utils.h" #include "Utils.h"
#include "dialogs/PlaceCall.h"
#include "dialogs/PreviewUploadOverlay.h" #include "dialogs/PreviewUploadOverlay.h"
#include "emoji/EmojiModel.h" #include "emoji/EmojiModel.h"
@ -593,50 +591,6 @@ InputBar::showPreview(const QMimeData &source, QString path, const QStringList &
}); });
} }
void
InputBar::callButton()
{
auto callManager_ = ChatPage::instance()->callManager();
if (callManager_->haveCallInvite()) {
return;
} else if (callManager_->isOnCall()) {
callManager_->hangUp();
} else {
auto current_room_ = room->roomId();
if (auto roomInfo = cache::singleRoomInfo(current_room_.toStdString());
roomInfo.member_count != 2) {
ChatPage::instance()->showNotification("Calls are limited to 1:1 rooms.");
} else {
std::vector<RoomMember> members(
cache::getMembers(current_room_.toStdString()));
const RoomMember &callee = members.front().user_id == utils::localUser()
? members.back()
: members.front();
auto dialog =
new dialogs::PlaceCall(callee.user_id,
callee.display_name,
QString::fromStdString(roomInfo.name),
QString::fromStdString(roomInfo.avatar_url),
ChatPage::instance()->userSettings(),
MainWindow::instance());
connect(dialog,
&dialogs::PlaceCall::voice,
callManager_,
[callManager_, current_room_]() {
callManager_->sendInvite(current_room_, false);
});
connect(dialog,
&dialogs::PlaceCall::video,
callManager_,
[callManager_, current_room_]() {
callManager_->sendInvite(current_room_, true);
});
utils::centerWidget(dialog, MainWindow::instance());
dialog->show();
}
}
}
void void
InputBar::startTyping() InputBar::startTyping()
{ {

View file

@ -41,7 +41,6 @@ public slots:
void updateState(int selectionStart, int selectionEnd, int cursorPosition, QString text); void updateState(int selectionStart, int selectionEnd, int cursorPosition, QString text);
void openFileSelection(); void openFileSelection();
bool uploading() const { return uploading_; } bool uploading() const { return uploading_; }
void callButton();
void message(QString body); void message(QString body);
QObject *completerFor(QString completerName); QObject *completerFor(QString completerName);