From 7124024977ccb237547b88b6a96a50ac6838c354 Mon Sep 17 00:00:00 2001 From: trilene Date: Thu, 17 Dec 2020 11:25:32 -0500 Subject: [PATCH] Make call invites less intrusive --- CMakeLists.txt | 2 - resources/qml/TimelineView.qml | 9 +- resources/qml/{ => voip}/ActiveCallBar.qml | 16 +-- resources/qml/voip/CallInviteBar.qml | 95 +++++++++++++ resources/qml/{ => voip}/VideoCall.qml | 0 resources/res.qrc | 5 +- src/CallManager.cpp | 100 ++++++++------ src/CallManager.h | 32 +++-- src/WebRTCSession.cpp | 2 + src/WebRTCSession.h | 1 + src/dialogs/AcceptCall.cpp | 152 --------------------- src/dialogs/AcceptCall.h | 39 ------ src/timeline/InputBar.cpp | 4 +- 13 files changed, 204 insertions(+), 253 deletions(-) rename resources/qml/{ => voip}/ActiveCallBar.qml (91%) create mode 100644 resources/qml/voip/CallInviteBar.qml rename resources/qml/{ => voip}/VideoCall.qml (100%) delete mode 100644 src/dialogs/AcceptCall.cpp delete mode 100644 src/dialogs/AcceptCall.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d0d6dd6..c674053f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -245,7 +245,6 @@ configure_file(cmake/nheko.h config/nheko.h) # set(SRC_FILES # Dialogs - src/dialogs/AcceptCall.cpp src/dialogs/CreateRoom.cpp src/dialogs/FallbackAuth.cpp src/dialogs/ImageOverlay.cpp @@ -464,7 +463,6 @@ feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAG qt5_wrap_cpp(MOC_HEADERS # Dialogs - src/dialogs/AcceptCall.h src/dialogs/CreateRoom.h src/dialogs/FallbackAuth.h src/dialogs/ImageOverlay.h diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index c71eb89f..3e134b35 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -1,6 +1,7 @@ import "./delegates" import "./device-verification" import "./emoji" +import "./voip" import QtGraphicalEffects 1.0 import QtQuick 2.9 import QtQuick.Controls 2.3 @@ -210,7 +211,7 @@ Page { } Loader { - source: CallManager.isOnVideoCall ? "VideoCall.qml" : "" + source: CallManager.isOnCall && CallManager.isVideo ? "voip/VideoCall.qml" : "" onLoaded: TimelineManager.setVideoCallItem() } @@ -223,6 +224,12 @@ Page { } + CallInviteBar { + id: callInviteBar + Layout.fillWidth: true + z: 3 + } + ActiveCallBar { Layout.fillWidth: true z: 3 diff --git a/resources/qml/ActiveCallBar.qml b/resources/qml/voip/ActiveCallBar.qml similarity index 91% rename from resources/qml/ActiveCallBar.qml rename to resources/qml/voip/ActiveCallBar.qml index 57b0877c..9efdb325 100644 --- a/resources/qml/ActiveCallBar.qml +++ b/resources/qml/voip/ActiveCallBar.qml @@ -2,18 +2,18 @@ import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 import im.nheko 1.0 +import "../" Rectangle { - id: activeCallBar visible: CallManager.isOnCall - color: "#2ECC71" + color: callInviteBar.color implicitHeight: visible ? rowLayout.height + 8 : 0 MouseArea { anchors.fill: parent onClicked: { - if (CallManager.isOnVideoCall) + if (CallManager.isVideo) stackLayout.currentIndex = stackLayout.currentIndex ? 0 : 1; } @@ -31,18 +31,18 @@ Rectangle { width: avatarSize height: avatarSize url: CallManager.callPartyAvatarUrl.replace("mxc://", "image://MxcImage/") - displayName: CallManager.callPartyName + displayName: CallManager.callParty } Label { font.pointSize: fontMetrics.font.pointSize * 1.1 - text: " " + CallManager.callPartyName + " " + text: " " + CallManager.callParty + " " } Image { Layout.preferredWidth: 24 Layout.preferredHeight: 24 - source: CallManager.isOnVideoCall ? "qrc:/icons/icons/ui/video-call.png" : "qrc:/icons/icons/ui/place-call.png" + source: CallManager.isVideo ? "qrc:/icons/icons/ui/video-call.png" : "qrc:/icons/icons/ui/place-call.png" } Label { @@ -99,7 +99,7 @@ Rectangle { PropertyChanges { target: stackLayout - currentIndex: CallManager.isOnVideoCall ? 1 : 0 + currentIndex: CallManager.isVideo ? 1 : 0 } }, @@ -148,7 +148,7 @@ Rectangle { } ImageButton { - visible: CallManager.isOnVideoCall + visible: CallManager.isVideo width: 24 height: 24 buttonTextColor: "#000000" diff --git a/resources/qml/voip/CallInviteBar.qml b/resources/qml/voip/CallInviteBar.qml new file mode 100644 index 00000000..6d4d2ac0 --- /dev/null +++ b/resources/qml/voip/CallInviteBar.qml @@ -0,0 +1,95 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Dialogs 1.3 +import QtQuick.Layouts 1.2 +import im.nheko 1.0 +import "../" + +Rectangle { + + visible: CallManager.haveCallInvite + color: "#2ECC71" + implicitHeight: visible ? rowLayout.height + 8 : 0 + + MessageDialog { + id: warningDialog + icon: StandardIcon.Warning + } + + RowLayout { + id: rowLayout + + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: 8 + + Avatar { + width: avatarSize + height: avatarSize + url: CallManager.callPartyAvatarUrl.replace("mxc://", "image://MxcImage/") + displayName: CallManager.callParty + } + + Label { + font.pointSize: fontMetrics.font.pointSize * 1.1 + text: " " + CallManager.callParty + " " + } + + Image { + Layout.preferredWidth: 24 + Layout.preferredHeight: 24 + source: CallManager.isVideo ? "qrc:/icons/icons/ui/video-call.png" : "qrc:/icons/icons/ui/place-call.png" + } + + Label { + font.pointSize: fontMetrics.font.pointSize * 1.1 + text: CallManager.isVideo ? "Video Call" : "Voice Call" + } + + Item { + Layout.fillWidth: true + } + + Button { + icon.source: CallManager.isVideo ? "qrc:/icons/icons/ui/video-call.png" : "qrc:/icons/icons/ui/place-call.png" + palette: colors + text: qsTr("Accept") + onClicked: { + if (CallManager.mics.length == 0) { + warningDialog.text = "No microphone found."; + warningDialog.open(); + return; + } + else if (!CallManager.mics.includes(Settings.microphone)) { + warningDialog.text = "Unknown microphone: " + Settings.microphone; + warningDialog.open(); + return; + } + if (CallManager.isVideo && CallManager.cameras.length > 0 && !CallManager.cameras.includes(Settings.camera)) { + warningDialog.text = "Unknown camera: " + Settings.camera; + warningDialog.open(); + return; + } + CallManager.acceptInvite(); + } + } + + Item { + implicitWidth: 8 + } + + Button { + icon.source: "qrc:/icons/icons/ui/end-call.png" + palette: colors + text: qsTr("Decline") + onClicked: { + CallManager.hangUp(); + } + } + + Item { + implicitWidth: 16 + } + } +} diff --git a/resources/qml/VideoCall.qml b/resources/qml/voip/VideoCall.qml similarity index 100% rename from resources/qml/VideoCall.qml rename to resources/qml/voip/VideoCall.qml diff --git a/resources/res.qrc b/resources/res.qrc index a01907ec..321fe12e 100644 --- a/resources/res.qrc +++ b/resources/res.qrc @@ -123,7 +123,6 @@ qtquickcontrols2.conf qml/TimelineView.qml - qml/ActiveCallBar.qml qml/Avatar.qml qml/Completer.qml qml/EncryptionIndicator.qml @@ -139,7 +138,6 @@ qml/TimelineRow.qml qml/TopBar.qml qml/TypingIndicator.qml - qml/VideoCall.qml qml/emoji/EmojiButton.qml qml/emoji/EmojiPicker.qml qml/UserProfile.qml @@ -159,6 +157,9 @@ qml/device-verification/NewVerificationRequest.qml qml/device-verification/Failed.qml qml/device-verification/Success.qml + qml/voip/ActiveCallBar.qml + qml/voip/CallInviteBar.qml + qml/voip/VideoCall.qml media/ring.ogg diff --git a/src/CallManager.cpp b/src/CallManager.cpp index cb523bc2..9864b203 100644 --- a/src/CallManager.cpp +++ b/src/CallManager.cpp @@ -10,10 +10,9 @@ #include "CallManager.h" #include "ChatPage.h" #include "Logging.h" -#include "MainWindow.h" #include "MatrixClient.h" +#include "UserSettingsPage.h" #include "Utils.h" -#include "dialogs/AcceptCall.h" #include "mtx/responses/turn_server.hpp" @@ -114,6 +113,22 @@ CallManager::CallManager(QObject *parent) emit newCallState(); }); + connect(&session_, &WebRTCSession::devicesChanged, this, [this]() { + if (ChatPage::instance()->userSettings()->microphone().isEmpty()) { + auto mics = session_.getDeviceNames(false, std::string()); + if (!mics.empty()) + ChatPage::instance()->userSettings()->setMicrophone( + QString::fromStdString(mics.front())); + } + if (ChatPage::instance()->userSettings()->camera().isEmpty()) { + auto cameras = session_.getDeviceNames(true, std::string()); + if (!cameras.empty()) + ChatPage::instance()->userSettings()->setCamera( + QString::fromStdString(cameras.front())); + } + emit devicesChanged(); + }); + connect(&player_, &QMediaPlayer::mediaStatusChanged, this, @@ -160,7 +175,8 @@ CallManager::sendInvite(const QString &roomid, bool isVideo) return; } - roomid_ = roomid; + isVideo_ = isVideo; + roomid_ = roomid; session_.setTurnServers(turnURIs_); generateCallID(); nhlog::ui()->debug( @@ -168,16 +184,14 @@ CallManager::sendInvite(const QString &roomid, bool isVideo) std::vector members(cache::getMembers(roomid.toStdString())); const RoomMember &callee = members.front().user_id == utils::localUser() ? members.back() : members.front(); - callPartyName_ = callee.display_name.isEmpty() ? callee.user_id : callee.display_name; + callParty_ = callee.display_name.isEmpty() ? callee.user_id : callee.display_name; callPartyAvatarUrl_ = QString::fromStdString(roomInfo.avatar_url); - emit newCallParty(); + emit newInviteState(); playRingtone(QUrl("qrc:/media/media/ringback.ogg"), true); if (!session_.createOffer(isVideo)) { emit ChatPage::instance()->showNotification("Problem setting up call."); endCall(); } - if (isVideo) - emit newVideoCallState(); } namespace { @@ -271,48 +285,41 @@ CallManager::handleEvent(const RoomEvent &callInviteEvent) std::vector members(cache::getMembers(callInviteEvent.room_id)); const RoomMember &caller = members.front().user_id == utils::localUser() ? members.back() : members.front(); - callPartyName_ = caller.display_name.isEmpty() ? caller.user_id : caller.display_name; + callParty_ = caller.display_name.isEmpty() ? caller.user_id : caller.display_name; callPartyAvatarUrl_ = QString::fromStdString(roomInfo.avatar_url); - emit newCallParty(); - auto dialog = new dialogs::AcceptCall(caller.user_id, - caller.display_name, - QString::fromStdString(roomInfo.name), - QString::fromStdString(roomInfo.avatar_url), - isVideo, - MainWindow::instance()); - connect(dialog, &dialogs::AcceptCall::accept, this, [this, callInviteEvent, isVideo]() { - MainWindow::instance()->hideOverlay(); - answerInvite(callInviteEvent.content, isVideo); - }); - connect(dialog, &dialogs::AcceptCall::reject, this, [this]() { - MainWindow::instance()->hideOverlay(); - hangUp(); - }); - MainWindow::instance()->showSolidOverlayModal(dialog); + + haveCallInvite_ = true; + isVideo_ = isVideo; + inviteSDP_ = callInviteEvent.content.sdp; + session_.refreshDevices(); + emit newInviteState(); } void -CallManager::answerInvite(const CallInvite &invite, bool isVideo) +CallManager::acceptInvite() { + if (!haveCallInvite_) + return; + stopRingtone(); std::string errorMessage; if (!session_.havePlugins(false, &errorMessage) || - (isVideo && !session_.havePlugins(true, &errorMessage))) { + (isVideo_ && !session_.havePlugins(true, &errorMessage))) { emit ChatPage::instance()->showNotification(QString::fromStdString(errorMessage)); hangUp(); return; } session_.setTurnServers(turnURIs_); - if (!session_.acceptOffer(invite.sdp)) { + if (!session_.acceptOffer(inviteSDP_)) { emit ChatPage::instance()->showNotification("Problem setting up call."); hangUp(); return; } session_.acceptICECandidates(remoteICECandidates_); remoteICECandidates_.clear(); - if (isVideo) - emit newVideoCallState(); + haveCallInvite_ = false; + emit newInviteState(); } void @@ -348,7 +355,8 @@ CallManager::handleEvent(const RoomEvent &callAnswerEvent) callid_ == callAnswerEvent.content.call_id) { emit ChatPage::instance()->showNotification("Call answered on another device."); stopRingtone(); - MainWindow::instance()->hideOverlay(); + haveCallInvite_ = false; + emit newInviteState(); return; } @@ -369,10 +377,8 @@ CallManager::handleEvent(const RoomEvent &callHangUpEvent) callHangUpReasonString(callHangUpEvent.content.reason), callHangUpEvent.sender); - if (callid_ == callHangUpEvent.content.call_id) { - MainWindow::instance()->hideOverlay(); + if (callid_ == callHangUpEvent.content.call_id) endCall(); - } } void @@ -392,6 +398,23 @@ CallManager::callsSupported() const #endif } +QStringList +CallManager::devices(bool isVideo) const +{ + QStringList ret; + const QString &defaultDevice = isVideo ? ChatPage::instance()->userSettings()->camera() + : ChatPage::instance()->userSettings()->microphone(); + std::vector devices = + session_.getDeviceNames(isVideo, defaultDevice.toStdString()); + ret.reserve(devices.size()); + std::transform(devices.cbegin(), + devices.cend(), + std::back_inserter(ret), + [](const auto &d) { return QString::fromStdString(d); }); + + return ret; +} + void CallManager::generateCallID() { @@ -404,9 +427,13 @@ void CallManager::clear() { roomid_.clear(); - callPartyName_.clear(); + callParty_.clear(); callPartyAvatarUrl_.clear(); callid_.clear(); + isVideo_ = false; + haveCallInvite_ = false; + emit newInviteState(); + inviteSDP_.clear(); remoteICECandidates_.clear(); } @@ -414,11 +441,8 @@ void CallManager::endCall() { stopRingtone(); - clear(); - bool isVideo = session_.isVideo(); session_.end(); - if (isVideo) - emit newVideoCallState(); + clear(); } void diff --git a/src/CallManager.h b/src/CallManager.h index d59a6249..e5571c88 100644 --- a/src/CallManager.h +++ b/src/CallManager.h @@ -16,48 +16,56 @@ namespace mtx::responses { struct TurnServer; } +class QStringList; class QUrl; class CallManager : public QObject { Q_OBJECT + Q_PROPERTY(bool haveCallInvite READ haveCallInvite NOTIFY newInviteState) Q_PROPERTY(bool isOnCall READ isOnCall NOTIFY newCallState) - Q_PROPERTY(bool isOnVideoCall READ isOnVideoCall NOTIFY newVideoCallState) + Q_PROPERTY(bool isVideo READ isVideo NOTIFY newInviteState) Q_PROPERTY(webrtc::State callState READ callState NOTIFY newCallState) - Q_PROPERTY(QString callPartyName READ callPartyName NOTIFY newCallParty) - Q_PROPERTY(QString callPartyAvatarUrl READ callPartyAvatarUrl NOTIFY newCallParty) + Q_PROPERTY(QString callParty READ callParty NOTIFY newInviteState) + Q_PROPERTY(QString callPartyAvatarUrl READ callPartyAvatarUrl NOTIFY newInviteState) Q_PROPERTY(bool isMicMuted READ isMicMuted NOTIFY micMuteChanged) Q_PROPERTY(bool callsSupported READ callsSupported CONSTANT) + Q_PROPERTY(QStringList mics READ mics NOTIFY devicesChanged) + Q_PROPERTY(QStringList cameras READ cameras NOTIFY devicesChanged) public: CallManager(QObject *); void sendInvite(const QString &roomid, bool isVideo); - void hangUp( - mtx::events::msg::CallHangUp::Reason = mtx::events::msg::CallHangUp::Reason::User); + bool haveCallInvite() const { return haveCallInvite_; } bool isOnCall() const { return session_.state() != webrtc::State::DISCONNECTED; } - bool isOnVideoCall() const { return session_.isVideo(); } + bool isVideo() const { return isVideo_; } webrtc::State callState() const { return session_.state(); } - QString callPartyName() const { return callPartyName_; } + QString callParty() const { return callParty_; } QString callPartyAvatarUrl() const { return callPartyAvatarUrl_; } bool isMicMuted() const { return session_.isMicMuted(); } bool callsSupported() const; + QStringList mics() const { return devices(false); } + QStringList cameras() const { return devices(true); } void refreshTurnServer(); public slots: void syncEvent(const mtx::events::collections::TimelineEvents &event); void toggleMicMute(); void toggleCameraView() { session_.toggleCameraView(); } + void acceptInvite(); + void hangUp( + mtx::events::msg::CallHangUp::Reason = mtx::events::msg::CallHangUp::Reason::User); signals: void newMessage(const QString &roomid, const mtx::events::msg::CallInvite &); void newMessage(const QString &roomid, const mtx::events::msg::CallCandidates &); void newMessage(const QString &roomid, const mtx::events::msg::CallAnswer &); void newMessage(const QString &roomid, const mtx::events::msg::CallHangUp &); + void newInviteState(); void newCallState(); - void newVideoCallState(); - void newCallParty(); void micMuteChanged(); + void devicesChanged(); void turnServerRetrieved(const mtx::responses::TurnServer &); private slots: @@ -66,10 +74,13 @@ private slots: private: WebRTCSession &session_; QString roomid_; - QString callPartyName_; + QString callParty_; QString callPartyAvatarUrl_; std::string callid_; const uint32_t timeoutms_ = 120000; + bool isVideo_ = false; + bool haveCallInvite_ = false; + std::string inviteSDP_; std::vector remoteICECandidates_; std::vector turnURIs_; QTimer turnServerTimer_; @@ -83,6 +94,7 @@ private: void handleEvent(const mtx::events::RoomEvent &); void answerInvite(const mtx::events::msg::CallInvite &, bool isVideo); void generateCallID(); + QStringList devices(bool isVideo) const; void clear(); void endCall(); void playRingtone(const QUrl &ringtone, bool repeat); diff --git a/src/WebRTCSession.cpp b/src/WebRTCSession.cpp index 0770a439..90a693a4 100644 --- a/src/WebRTCSession.cpp +++ b/src/WebRTCSession.cpp @@ -242,12 +242,14 @@ newBusMessage(GstBus *bus G_GNUC_UNUSED, GstMessage *msg, gpointer user_data) GstDevice *device; gst_message_parse_device_added(msg, &device); addDevice(device); + emit WebRTCSession::instance().devicesChanged(); break; } case GST_MESSAGE_DEVICE_REMOVED: { GstDevice *device; gst_message_parse_device_removed(msg, &device); removeDevice(device, false); + emit WebRTCSession::instance().devicesChanged(); break; } case GST_MESSAGE_DEVICE_CHANGED: { diff --git a/src/WebRTCSession.h b/src/WebRTCSession.h index 57002f8f..fe82725f 100644 --- a/src/WebRTCSession.h +++ b/src/WebRTCSession.h @@ -75,6 +75,7 @@ signals: const std::vector &); void newICECandidate(const mtx::events::msg::CallCandidates::Candidate &); void stateChanged(webrtc::State); + void devicesChanged(); private slots: void setState(webrtc::State state) { state_ = state; } diff --git a/src/dialogs/AcceptCall.cpp b/src/dialogs/AcceptCall.cpp deleted file mode 100644 index 3d25ad82..00000000 --- a/src/dialogs/AcceptCall.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include -#include -#include -#include -#include - -#include "ChatPage.h" -#include "Config.h" -#include "UserSettingsPage.h" -#include "Utils.h" -#include "WebRTCSession.h" -#include "dialogs/AcceptCall.h" -#include "ui/Avatar.h" - -namespace dialogs { - -AcceptCall::AcceptCall(const QString &caller, - const QString &displayName, - const QString &roomName, - const QString &avatarUrl, - bool isVideo, - 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; - } - if (isVideo && !session->havePlugins(true, &errorMessage)) { - emit ChatPage::instance()->showNotification(QString::fromStdString(errorMessage)); - emit close(); - return; - } - - session->refreshDevices(); - microphones_ = session->getDeviceNames( - false, ChatPage::instance()->userSettings()->microphone().toStdString()); - if (microphones_.empty()) { - emit ChatPage::instance()->showNotification( - tr("Incoming call: No microphone found.")); - emit close(); - return; - } - if (isVideo) - cameras_ = session->getDeviceNames( - true, ChatPage::instance()->userSettings()->camera().toStdString()); - - setAutoFillBackground(true); - setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); - setWindowModality(Qt::WindowModal); - setAttribute(Qt::WA_DeleteOnClose, true); - - setMinimumWidth(conf::modals::MIN_WIDGET_WIDTH); - setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); - - auto layout = new QVBoxLayout(this); - layout->setSpacing(conf::modals::WIDGET_SPACING); - layout->setMargin(conf::modals::WIDGET_MARGIN); - - QFont f; - f.setPointSizeF(f.pointSizeF()); - - QFont labelFont; - labelFont.setWeight(QFont::Medium); - - QLabel *displayNameLabel = nullptr; - if (!displayName.isEmpty() && displayName != caller) { - displayNameLabel = new QLabel(displayName, this); - labelFont.setPointSizeF(f.pointSizeF() * 2); - displayNameLabel->setFont(labelFont); - displayNameLabel->setAlignment(Qt::AlignCenter); - } - - QLabel *callerLabel = new QLabel(caller, this); - labelFont.setPointSizeF(f.pointSizeF() * 1.2); - callerLabel->setFont(labelFont); - callerLabel->setAlignment(Qt::AlignCenter); - - auto avatar = new Avatar(this, QFontMetrics(f).height() * 6); - if (!avatarUrl.isEmpty()) - avatar->setImage(avatarUrl); - else - avatar->setLetter(utils::firstChar(roomName)); - - const int iconSize = 22; - QLabel *callTypeIndicator = new QLabel(this); - callTypeIndicator->setPixmap( - QIcon(isVideo ? ":/icons/icons/ui/video-call.png" : ":/icons/icons/ui/place-call.png") - .pixmap(QSize(iconSize * 2, iconSize * 2))); - - QLabel *callTypeLabel = new QLabel(isVideo ? tr("Video Call") : tr("Voice Call"), this); - labelFont.setPointSizeF(f.pointSizeF() * 1.1); - callTypeLabel->setFont(labelFont); - callTypeLabel->setAlignment(Qt::AlignCenter); - - auto buttonLayout = new QHBoxLayout; - buttonLayout->setSpacing(18); - acceptBtn_ = new QPushButton(tr("Accept"), this); - acceptBtn_->setDefault(true); - acceptBtn_->setIcon( - QIcon(isVideo ? ":/icons/icons/ui/video-call.png" : ":/icons/icons/ui/place-call.png")); - acceptBtn_->setIconSize(QSize(iconSize, iconSize)); - - rejectBtn_ = new QPushButton(tr("Reject"), this); - rejectBtn_->setIcon(QIcon(":/icons/icons/ui/end-call.png")); - rejectBtn_->setIconSize(QSize(iconSize, iconSize)); - buttonLayout->addWidget(acceptBtn_); - buttonLayout->addWidget(rejectBtn_); - - microphoneCombo_ = new QComboBox(this); - for (const auto &m : microphones_) - microphoneCombo_->addItem(QIcon(":/icons/icons/ui/microphone-unmute.png"), - QString::fromStdString(m)); - - if (!cameras_.empty()) { - cameraCombo_ = new QComboBox(this); - for (const auto &c : cameras_) - cameraCombo_->addItem(QIcon(":/icons/icons/ui/video-call.png"), - QString::fromStdString(c)); - } - - if (displayNameLabel) - layout->addWidget(displayNameLabel, 0, Qt::AlignCenter); - layout->addWidget(callerLabel, 0, Qt::AlignCenter); - layout->addWidget(avatar, 0, Qt::AlignCenter); - layout->addWidget(callTypeIndicator, 0, Qt::AlignCenter); - layout->addWidget(callTypeLabel, 0, Qt::AlignCenter); - layout->addLayout(buttonLayout); - layout->addWidget(microphoneCombo_); - if (cameraCombo_) - layout->addWidget(cameraCombo_); - - connect(acceptBtn_, &QPushButton::clicked, this, [this]() { - ChatPage::instance()->userSettings()->setMicrophone( - QString::fromStdString(microphones_[microphoneCombo_->currentIndex()])); - if (cameraCombo_) { - ChatPage::instance()->userSettings()->setCamera( - QString::fromStdString(cameras_[cameraCombo_->currentIndex()])); - } - emit accept(); - emit close(); - }); - connect(rejectBtn_, &QPushButton::clicked, this, [this]() { - emit reject(); - emit close(); - }); -} - -} diff --git a/src/dialogs/AcceptCall.h b/src/dialogs/AcceptCall.h deleted file mode 100644 index 76ca7ae1..00000000 --- a/src/dialogs/AcceptCall.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include -#include - -#include - -class QComboBox; -class QPushButton; -class QString; - -namespace dialogs { - -class AcceptCall : public QWidget -{ - Q_OBJECT - -public: - AcceptCall(const QString &caller, - const QString &displayName, - const QString &roomName, - const QString &avatarUrl, - bool isVideo, - QWidget *parent = nullptr); - -signals: - void accept(); - void reject(); - -private: - QPushButton *acceptBtn_ = nullptr; - QPushButton *rejectBtn_ = nullptr; - QComboBox *microphoneCombo_ = nullptr; - QComboBox *cameraCombo_ = nullptr; - std::vector microphones_; - std::vector cameras_; -}; - -} diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index 2f50a7cc..78c8c6a3 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -597,7 +597,9 @@ void InputBar::callButton() { auto callManager_ = ChatPage::instance()->callManager(); - if (callManager_->isOnCall()) { + if (callManager_->haveCallInvite()) { + return; + } else if (callManager_->isOnCall()) { callManager_->hangUp(); } else { auto current_room_ = room->roomId();