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();