mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-04-21 21:52:03 +02:00
videocallpage: handle conference infos
Change-Id: I4cfc7c9c525c66f4e483089864bec059c388a1bd
This commit is contained in:
parent
8940f3c46e
commit
6607e0e9cf
14 changed files with 629 additions and 20 deletions
|
@ -1,6 +1,6 @@
|
||||||
[gerrit]
|
[gerrit]
|
||||||
host=gerrit-ring.savoirfairelinux.com
|
host=gerrit-ring.savoirfairelinux.com
|
||||||
port=29420
|
port=29420
|
||||||
project=ring-client-window.git
|
project=jami-client-qt.git
|
||||||
defaultremote=origin
|
defaultremote=origin
|
||||||
defaultbranch=master
|
defaultbranch=master
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<svg fill="#ffffff" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M0 0h24v24H0z" fill="none"/>
|
<path d="M0 0h24v24H0z" fill="none"/>
|
||||||
<path d="M12 9c-1.6 0-3.15.25-4.6.72v3.1c0 .39-.23.74-.56.9-.98.49-1.87 1.12-2.66 1.85-.18.18-.43.28-.7.28-.28 0-.53-.11-.71-.29L.29 13.08c-.18-.17-.29-.42-.29-.7 0-.28.11-.53.29-.71C3.34 8.78 7.46 7 12 7s8.66 1.78 11.71 4.67c.18.18.29.43.29.71 0 .28-.11.53-.29.71l-2.48 2.48c-.18.18-.43.29-.71.29-.27 0-.52-.11-.7-.28-.79-.74-1.69-1.36-2.67-1.85-.33-.16-.56-.5-.56-.9v-3.1C15.15 9.25 13.6 9 12 9z"/>
|
<path d="M12 9c-1.6 0-3.15.25-4.6.72v3.1c0 .39-.23.74-.56.9-.98.49-1.87 1.12-2.66 1.85-.18.18-.43.28-.7.28-.28 0-.53-.11-.71-.29L.29 13.08c-.18-.17-.29-.42-.29-.7 0-.28.11-.53.29-.71C3.34 8.78 7.46 7 12 7s8.66 1.78 11.71 4.67c.18.18.29.43.29.71 0 .28-.11.53-.29.71l-2.48 2.48c-.18.18-.43.29-.71.29-.27 0-.52-.11-.7-.28-.79-.74-1.69-1.36-2.67-1.85-.33-.16-.56-.5-.56-.9v-3.1C15.15 9.25 13.6 9 12 9z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 553 B After Width: | Height: | Size: 538 B |
2
qml.qrc
2
qml.qrc
|
@ -67,6 +67,7 @@
|
||||||
<file>src/mainview/components/ContactSearchBar.qml</file>
|
<file>src/mainview/components/ContactSearchBar.qml</file>
|
||||||
<file>src/mainview/components/VideoCallPage.qml</file>
|
<file>src/mainview/components/VideoCallPage.qml</file>
|
||||||
<file>src/mainview/components/CallAdvancedOptions.qml</file>
|
<file>src/mainview/components/CallAdvancedOptions.qml</file>
|
||||||
|
<file>src/mainview/components/ParticipantOverlay.qml</file>
|
||||||
<file>src/mainview/components/ChangeLogScrollView.qml</file>
|
<file>src/mainview/components/ChangeLogScrollView.qml</file>
|
||||||
<file>src/mainview/components/ProjectCreditsScrollView.qml</file>
|
<file>src/mainview/components/ProjectCreditsScrollView.qml</file>
|
||||||
<file>src/mainview/components/AccountComboBoxPopup.qml</file>
|
<file>src/mainview/components/AccountComboBoxPopup.qml</file>
|
||||||
|
@ -77,6 +78,7 @@
|
||||||
<file>src/commoncomponents/GeneralMenuItem.qml</file>
|
<file>src/commoncomponents/GeneralMenuItem.qml</file>
|
||||||
<file>src/mainview/components/ConversationSmartListContextMenu.qml</file>
|
<file>src/mainview/components/ConversationSmartListContextMenu.qml</file>
|
||||||
<file>src/mainview/components/CallViewContextMenu.qml</file>
|
<file>src/mainview/components/CallViewContextMenu.qml</file>
|
||||||
|
<file>src/mainview/components/ParticipantContextMenu.qml</file>
|
||||||
<file>src/commoncomponents/GeneralMenuSeparator.qml</file>
|
<file>src/commoncomponents/GeneralMenuSeparator.qml</file>
|
||||||
<file>src/mainview/components/UserProfile.qml</file>
|
<file>src/mainview/components/UserProfile.qml</file>
|
||||||
<file>src/mainview/js/videodevicecontextmenuitemcreation.js</file>
|
<file>src/mainview/js/videodevicecontextmenuitemcreation.js</file>
|
||||||
|
|
|
@ -37,7 +37,7 @@ CallAdapter::~CallAdapter() {}
|
||||||
void
|
void
|
||||||
CallAdapter::initQmlObject()
|
CallAdapter::initQmlObject()
|
||||||
{
|
{
|
||||||
connectCallStatusChanged(LRCInstance::getCurrAccId());
|
connectCallModel(LRCInstance::getCurrAccId());
|
||||||
|
|
||||||
connect(&LRCInstance::behaviorController(),
|
connect(&LRCInstance::behaviorController(),
|
||||||
&BehaviorController::showIncomingCallView,
|
&BehaviorController::showIncomingCallView,
|
||||||
|
@ -233,12 +233,91 @@ CallAdapter::shouldShowPreview(bool force)
|
||||||
return shouldShowPreview;
|
return shouldShowPreview;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariantList
|
||||||
|
CallAdapter::getConferencesInfos()
|
||||||
|
{
|
||||||
|
QVariantList map;
|
||||||
|
auto convInfo = LRCInstance::getConversationFromConvUid(convUid_, accountId_);
|
||||||
|
if (convInfo.uid.isEmpty())
|
||||||
|
return map;
|
||||||
|
auto callId = convInfo.confId.isEmpty()? convInfo.callId : convInfo.confId;
|
||||||
|
if (!callId.isEmpty()) {
|
||||||
|
try {
|
||||||
|
auto call = LRCInstance::getCurrentCallModel()->getCall(callId);
|
||||||
|
for (const auto& participant: call.participantsInfos) {
|
||||||
|
QJsonObject data;
|
||||||
|
data["x"] = participant["x"].toInt();
|
||||||
|
data["y"] = participant["y"].toInt();
|
||||||
|
data["w"] = participant["w"].toInt();
|
||||||
|
data["h"] = participant["h"].toInt();
|
||||||
|
data["active"] = participant["active"] == "true";
|
||||||
|
auto bestName = participant["uri"];
|
||||||
|
auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId_);
|
||||||
|
data["isLocal"] = false;
|
||||||
|
if (bestName == accInfo.profileInfo.uri) {
|
||||||
|
bestName = tr("me");
|
||||||
|
data["isLocal"] = true;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
auto &contact = LRCInstance::getCurrentAccountInfo().contactModel->getContact(participant["uri"]);
|
||||||
|
bestName = Utils::bestNameForContact(contact);
|
||||||
|
} catch (...) {}
|
||||||
|
}
|
||||||
|
data["bestName"] = bestName;
|
||||||
|
|
||||||
|
map.push_back(QVariant(data));
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
} catch (...) {}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CallAdapter::connectCallStatusChanged(const QString &accountId)
|
CallAdapter::connectCallModel(const QString &accountId)
|
||||||
{
|
{
|
||||||
auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId);
|
auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId);
|
||||||
|
|
||||||
QObject::disconnect(callStatusChangedConnection_);
|
QObject::disconnect(callStatusChangedConnection_);
|
||||||
|
QObject::disconnect(onParticipantsChangedConnection_);
|
||||||
|
|
||||||
|
onParticipantsChangedConnection_ = QObject::connect(
|
||||||
|
accInfo.callModel.get(),
|
||||||
|
&lrc::api::NewCallModel::onParticipantsChanged,
|
||||||
|
[this, accountId](const QString &confId) {
|
||||||
|
auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId);
|
||||||
|
auto &callModel = accInfo.callModel;
|
||||||
|
auto call = callModel->getCall(confId);
|
||||||
|
auto convInfo = LRCInstance::getConversationFromCallId(confId);
|
||||||
|
if (!convInfo.uid.isEmpty()) {
|
||||||
|
// Convert to QML
|
||||||
|
QVariantList map;
|
||||||
|
for (const auto& participant: call.participantsInfos) {
|
||||||
|
QJsonObject data;
|
||||||
|
data["x"] = participant["x"].toInt();
|
||||||
|
data["y"] = participant["y"].toInt();
|
||||||
|
data["w"] = participant["w"].toInt();
|
||||||
|
data["h"] = participant["h"].toInt();
|
||||||
|
data["uri"] = participant["uri"];
|
||||||
|
data["active"] = participant["active"] == "true";
|
||||||
|
auto bestName = participant["uri"];
|
||||||
|
data["isLocal"] = false;
|
||||||
|
auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId_);
|
||||||
|
if (bestName == accInfo.profileInfo.uri) {
|
||||||
|
bestName = tr("me");
|
||||||
|
data["isLocal"] = true;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
auto &contact = LRCInstance::getCurrentAccountInfo().contactModel->getContact(participant["uri"]);
|
||||||
|
bestName = Utils::bestNameForContact(contact);
|
||||||
|
} catch (...) {}
|
||||||
|
}
|
||||||
|
data["bestName"] = bestName;
|
||||||
|
map.push_back(QVariant(data));
|
||||||
|
}
|
||||||
|
emit updateParticipantsInfos(map, accountId, confId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
callStatusChangedConnection_ = QObject::connect(
|
callStatusChangedConnection_ = QObject::connect(
|
||||||
accInfo.callModel.get(),
|
accInfo.callModel.get(),
|
||||||
|
@ -345,7 +424,7 @@ CallAdapter::updateCallOverlay(const lrc::api::conversation::Info &convInfo)
|
||||||
bool isAudioOnly = call->isAudioOnly && !isPaused;
|
bool isAudioOnly = call->isAudioOnly && !isPaused;
|
||||||
bool isAudioMuted = call->audioMuted && (call->status != lrc::api::call::Status::PAUSED);
|
bool isAudioMuted = call->audioMuted && (call->status != lrc::api::call::Status::PAUSED);
|
||||||
bool isVideoMuted = call->videoMuted && !isPaused && !call->isAudioOnly;
|
bool isVideoMuted = call->videoMuted && !isPaused && !call->isAudioOnly;
|
||||||
bool isRecording = accInfo.callModel->isRecording(convInfo.callId);
|
bool isRecording = isRecordingThisCall();
|
||||||
|
|
||||||
emit updateOverlay(isPaused,
|
emit updateOverlay(isPaused,
|
||||||
isAudioOnly,
|
isAudioOnly,
|
||||||
|
@ -359,16 +438,16 @@ CallAdapter::updateCallOverlay(const lrc::api::conversation::Info &convInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CallAdapter::hangUpThisCall()
|
CallAdapter::hangupCall(const QString& uri)
|
||||||
{
|
{
|
||||||
auto convInfo = LRCInstance::getConversationFromConvUid(convUid_, accountId_);
|
auto convInfo = LRCInstance::getConversationFromPeerUri(uri, accountId_);
|
||||||
if (!convInfo.uid.isEmpty()) {
|
if (!convInfo.uid.isEmpty()) {
|
||||||
auto callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
|
auto callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
|
||||||
if (callModel->hasCall(convInfo.callId)) {
|
if (callModel->hasCall(convInfo.callId)) {
|
||||||
/*
|
/*
|
||||||
* Store the last remaining participant of the conference,
|
* Store the last remaining participant of the conference,
|
||||||
* so we can switch the smartlist index after termination.
|
* so we can switch the smartlist index after termination.
|
||||||
*/
|
*/
|
||||||
if (!convInfo.confId.isEmpty()) {
|
if (!convInfo.confId.isEmpty()) {
|
||||||
auto callList = LRCInstance::getAPI().getConferenceSubcalls(convInfo.confId);
|
auto callList = LRCInstance::getAPI().getConferenceSubcalls(convInfo.confId);
|
||||||
if (callList.size() == 2) {
|
if (callList.size() == 2) {
|
||||||
|
@ -379,6 +458,73 @@ CallAdapter::hangUpThisCall()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callModel->hangUp(convInfo.callId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CallAdapter::maximizeParticipant(const QString& uri, bool isActive)
|
||||||
|
{
|
||||||
|
auto callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
|
||||||
|
auto confId = LRCInstance::getCurrentConversation().confId;
|
||||||
|
QString callId;
|
||||||
|
if (LRCInstance::getCurrentAccountInfo().profileInfo.uri != uri) {
|
||||||
|
auto convInfo = LRCInstance::getConversationFromPeerUri(uri, accountId_);
|
||||||
|
if (!convInfo.uid.isEmpty()) {
|
||||||
|
callId = convInfo.callId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
auto call = callModel->getCall(confId);
|
||||||
|
switch (call.layout) {
|
||||||
|
case lrc::api::call::Layout::GRID:
|
||||||
|
callModel->setActiveParticipant(confId, callId);
|
||||||
|
callModel->setConferenceLayout(confId, lrc::api::call::Layout::ONE_WITH_SMALL);
|
||||||
|
break;
|
||||||
|
case lrc::api::call::Layout::ONE_WITH_SMALL:
|
||||||
|
callModel->setActiveParticipant(confId, callId);
|
||||||
|
callModel->setConferenceLayout(confId,
|
||||||
|
isActive? lrc::api::call::Layout::ONE : lrc::api::call::Layout::ONE_WITH_SMALL);
|
||||||
|
break;
|
||||||
|
case lrc::api::call::Layout::ONE:
|
||||||
|
callModel->setActiveParticipant(confId, callId);
|
||||||
|
callModel->setConferenceLayout(confId, lrc::api::call::Layout::GRID);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
} catch (...) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CallAdapter::minimizeParticipant()
|
||||||
|
{
|
||||||
|
auto callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
|
||||||
|
auto confId = LRCInstance::getCurrentConversation().confId;
|
||||||
|
try {
|
||||||
|
auto call = callModel->getCall(confId);
|
||||||
|
switch (call.layout) {
|
||||||
|
case lrc::api::call::Layout::GRID:
|
||||||
|
break;
|
||||||
|
case lrc::api::call::Layout::ONE_WITH_SMALL:
|
||||||
|
callModel->setConferenceLayout(confId, lrc::api::call::Layout::GRID);
|
||||||
|
break;
|
||||||
|
case lrc::api::call::Layout::ONE:
|
||||||
|
callModel->setConferenceLayout(confId, lrc::api::call::Layout::ONE_WITH_SMALL);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
} catch (...) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CallAdapter::hangUpThisCall()
|
||||||
|
{
|
||||||
|
auto convInfo = LRCInstance::getConversationFromConvUid(convUid_, accountId_);
|
||||||
|
if (!convInfo.uid.isEmpty()) {
|
||||||
|
auto callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
|
||||||
|
if (!convInfo.confId.isEmpty() && callModel->hasCall(convInfo.confId)) {
|
||||||
|
callModel->hangUp(convInfo.confId);
|
||||||
|
} else if (callModel->hasCall(convInfo.callId)) {
|
||||||
callModel->hangUp(convInfo.callId);
|
callModel->hangUp(convInfo.callId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -393,6 +539,38 @@ CallAdapter::isRecordingThisCall()
|
||||||
|| accInfo.callModel->isRecording(convInfo.callId);
|
|| accInfo.callModel->isRecording(convInfo.callId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CallAdapter::isCurrentMaster() const
|
||||||
|
{
|
||||||
|
auto convInfo = LRCInstance::getConversationFromConvUid(convUid_, accountId_);
|
||||||
|
if (!convInfo.uid.isEmpty()) {
|
||||||
|
auto callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
|
||||||
|
try {
|
||||||
|
if (!convInfo.confId.isEmpty() && callModel->hasCall(convInfo.confId)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
auto call = callModel->getCall(convInfo.callId);
|
||||||
|
return call.participantsInfos.size() == 0;
|
||||||
|
}
|
||||||
|
} catch (...) {}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
CallAdapter::getCurrentLayoutType() const
|
||||||
|
{
|
||||||
|
auto convInfo = LRCInstance::getConversationFromConvUid(convUid_, accountId_);
|
||||||
|
if (!convInfo.uid.isEmpty()) {
|
||||||
|
auto callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
|
||||||
|
try {
|
||||||
|
auto call = callModel->getCall(convInfo.confId);
|
||||||
|
return Utils::toUnderlyingValue(call.layout);
|
||||||
|
} catch (...) {}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CallAdapter::holdThisCallToggle()
|
CallAdapter::holdThisCallToggle()
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
class CallAdapter : public QmlAdapterBase
|
class CallAdapter : public QmlAdapterBase
|
||||||
{
|
{
|
||||||
|
@ -44,17 +45,23 @@ public:
|
||||||
Q_INVOKABLE void refuseACall(const QString &accountId, const QString &convUid);
|
Q_INVOKABLE void refuseACall(const QString &accountId, const QString &convUid);
|
||||||
Q_INVOKABLE void acceptACall(const QString &accountId, const QString &convUid);
|
Q_INVOKABLE void acceptACall(const QString &accountId, const QString &convUid);
|
||||||
|
|
||||||
Q_INVOKABLE void connectCallStatusChanged(const QString &accountId);
|
Q_INVOKABLE void connectCallModel(const QString &accountId);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For Call Overlay
|
* For Call Overlay
|
||||||
*/
|
*/
|
||||||
|
Q_INVOKABLE void hangupCall(const QString& uri);
|
||||||
|
Q_INVOKABLE void maximizeParticipant(const QString& uri, bool isActive);
|
||||||
|
Q_INVOKABLE void minimizeParticipant();
|
||||||
Q_INVOKABLE void hangUpThisCall();
|
Q_INVOKABLE void hangUpThisCall();
|
||||||
|
Q_INVOKABLE bool isCurrentMaster() const;
|
||||||
|
Q_INVOKABLE int getCurrentLayoutType() const;
|
||||||
Q_INVOKABLE void holdThisCallToggle();
|
Q_INVOKABLE void holdThisCallToggle();
|
||||||
Q_INVOKABLE void muteThisCallToggle();
|
Q_INVOKABLE void muteThisCallToggle();
|
||||||
Q_INVOKABLE void recordThisCallToggle();
|
Q_INVOKABLE void recordThisCallToggle();
|
||||||
Q_INVOKABLE void videoPauseThisCallToggle();
|
Q_INVOKABLE void videoPauseThisCallToggle();
|
||||||
Q_INVOKABLE bool isRecordingThisCall();
|
Q_INVOKABLE bool isRecordingThisCall();
|
||||||
|
Q_INVOKABLE QVariantList getConferencesInfos();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void showOutgoingCallPage(const QString &accountId, const QString &convUid);
|
void showOutgoingCallPage(const QString &accountId, const QString &convUid);
|
||||||
|
@ -66,6 +73,7 @@ signals:
|
||||||
void closePotentialIncomingCallPageWindow(const QString &accountId, const QString &convUid);
|
void closePotentialIncomingCallPageWindow(const QString &accountId, const QString &convUid);
|
||||||
void callStatusChanged(const QString &status, const QString &accountId, const QString &convUid);
|
void callStatusChanged(const QString &status, const QString &accountId, const QString &convUid);
|
||||||
void updateConversationSmartList();
|
void updateConversationSmartList();
|
||||||
|
void updateParticipantsInfos(const QVariantList& infos, const QString &accountId, const QString &callId);
|
||||||
|
|
||||||
void incomingCallNeedToSetupMainView(const QString &accountId, const QString &convUid);
|
void incomingCallNeedToSetupMainView(const QString &accountId, const QString &convUid);
|
||||||
void previewVisibilityNeedToChange(bool visible);
|
void previewVisibilityNeedToChange(bool visible);
|
||||||
|
@ -103,6 +111,7 @@ private:
|
||||||
QString convUid_;
|
QString convUid_;
|
||||||
|
|
||||||
QMetaObject::Connection callStatusChangedConnection_;
|
QMetaObject::Connection callStatusChangedConnection_;
|
||||||
|
QMetaObject::Connection onParticipantsChangedConnection_;
|
||||||
QMetaObject::Connection closeIncomingCallPageConnection_;
|
QMetaObject::Connection closeIncomingCallPageConnection_;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -51,15 +51,48 @@ DistantRenderer::setRendererId(const QString &id)
|
||||||
update(QRect(0, 0, width(), height()));
|
update(QRect(0, 0, width(), height()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
DistantRenderer::getXOffset() const
|
||||||
|
{
|
||||||
|
return xOffset_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
DistantRenderer::getYOffset() const
|
||||||
|
{
|
||||||
|
return yOffset_;
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
DistantRenderer::getScaledWidth() const
|
||||||
|
{
|
||||||
|
return scaledWidth_;
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
DistantRenderer::getScaledHeight() const
|
||||||
|
{
|
||||||
|
return scaledHeight_;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DistantRenderer::paint(QPainter *painter)
|
DistantRenderer::paint(QPainter *painter)
|
||||||
{
|
{
|
||||||
auto distantImage = LRCInstance::renderer()->getFrame(distantRenderId_);
|
auto distantImage = LRCInstance::renderer()->getFrame(distantRenderId_);
|
||||||
if (distantImage) {
|
if (distantImage) {
|
||||||
auto scaledDistant = distantImage->scaled(size().toSize(), Qt::KeepAspectRatio);
|
auto scaledDistant = distantImage->scaled(size().toSize(), Qt::KeepAspectRatio);
|
||||||
auto xDiff = (width() - scaledDistant.width()) / 2;
|
auto tempScaledWidth = static_cast<int>(scaledWidth_*1000);
|
||||||
auto yDiff = (height() - scaledDistant.height()) / 2;
|
auto tempScaledHeight = static_cast<int>(scaledHeight_*1000);
|
||||||
painter->drawImage(QRect(xDiff, yDiff, scaledDistant.width(), scaledDistant.height()),
|
auto tempXOffset = xOffset_;
|
||||||
|
auto tempYOffset = yOffset_;
|
||||||
|
scaledWidth_ = static_cast<double>(scaledDistant.width())/static_cast<double>(distantImage->width());
|
||||||
|
scaledHeight_ = static_cast<double>(scaledDistant.height())/static_cast<double>(distantImage->height());
|
||||||
|
xOffset_ = (width() - scaledDistant.width()) / 2;
|
||||||
|
yOffset_ = (height() - scaledDistant.height()) / 2;
|
||||||
|
if (tempXOffset != xOffset_ or tempYOffset != yOffset_ or static_cast<int>(scaledWidth_*1000) != tempScaledWidth or static_cast<int>(scaledHeight_*1000) != tempScaledHeight) {
|
||||||
|
emit offsetChanged();
|
||||||
|
}
|
||||||
|
painter->drawImage(QRect(xOffset_, yOffset_, scaledDistant.width(), scaledDistant.height()),
|
||||||
scaledDistant);
|
scaledDistant);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -34,6 +34,13 @@ public:
|
||||||
~DistantRenderer();
|
~DistantRenderer();
|
||||||
|
|
||||||
Q_INVOKABLE void setRendererId(const QString &id);
|
Q_INVOKABLE void setRendererId(const QString &id);
|
||||||
|
Q_INVOKABLE int getXOffset() const;
|
||||||
|
Q_INVOKABLE int getYOffset() const;
|
||||||
|
Q_INVOKABLE double getScaledWidth() const;
|
||||||
|
Q_INVOKABLE double getScaledHeight() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void offsetChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void paint(QPainter *painter);
|
void paint(QPainter *painter);
|
||||||
|
@ -42,4 +49,8 @@ private:
|
||||||
* Unique DistantRenderId for each call.
|
* Unique DistantRenderId for each call.
|
||||||
*/
|
*/
|
||||||
QString distantRenderId_;
|
QString distantRenderId_;
|
||||||
|
int xOffset_ {0};
|
||||||
|
int yOffset_ {0};
|
||||||
|
double scaledWidth_ {0};
|
||||||
|
double scaledHeight_ {0};
|
||||||
};
|
};
|
|
@ -229,7 +229,7 @@ public:
|
||||||
{
|
{
|
||||||
return getConversation(
|
return getConversation(
|
||||||
!accountId.isEmpty() ? accountId : getCurrAccId(),
|
!accountId.isEmpty() ? accountId : getCurrAccId(),
|
||||||
[&](const conversation::Info &conv) -> bool { return callId == conv.callId; },
|
[&](const conversation::Info &conv) -> bool { return callId == conv.callId or callId == conv.confId; },
|
||||||
filtered);
|
filtered);
|
||||||
}
|
}
|
||||||
static const conversation::Info &
|
static const conversation::Info &
|
||||||
|
|
|
@ -35,6 +35,9 @@ Rectangle {
|
||||||
|
|
||||||
signal overlayChatButtonClicked
|
signal overlayChatButtonClicked
|
||||||
|
|
||||||
|
property var participantOverlays: []
|
||||||
|
property var participantComponent: Qt.createComponent("ParticipantOverlay.qml")
|
||||||
|
|
||||||
function setRecording(isRecording) {
|
function setRecording(isRecording) {
|
||||||
callViewContextMenu.isRecording = isRecording
|
callViewContextMenu.isRecording = isRecording
|
||||||
recordingRect.visible = isRecording
|
recordingRect.visible = isRecording
|
||||||
|
@ -52,6 +55,10 @@ Rectangle {
|
||||||
isConferenceCall)
|
isConferenceCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateMaster() {
|
||||||
|
callOverlayButtonGroup.updateMaster()
|
||||||
|
}
|
||||||
|
|
||||||
function showOnHoldImage(visible) {
|
function showOnHoldImage(visible) {
|
||||||
onHoldImage.visible = visible
|
onHoldImage.visible = visible
|
||||||
}
|
}
|
||||||
|
@ -60,6 +67,41 @@ Rectangle {
|
||||||
ContactPickerCreation.closeContactPicker()
|
ContactPickerCreation.closeContactPicker()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleParticipantsInfo(infos) {
|
||||||
|
videoCallOverlay.updateMaster()
|
||||||
|
var isMaster = CallAdapter.isCurrentMaster()
|
||||||
|
for (var p in participantOverlays) {
|
||||||
|
if (participantOverlays[p])
|
||||||
|
participantOverlays[p].destroy()
|
||||||
|
}
|
||||||
|
participantOverlays = []
|
||||||
|
if (infos.length == 0) {
|
||||||
|
previewRenderer.visible = true
|
||||||
|
} else {
|
||||||
|
previewRenderer.visible = false
|
||||||
|
for (var infoVariant in infos) {
|
||||||
|
var hover = participantComponent.createObject(callOverlayRectMouseArea, {
|
||||||
|
x: distantRenderer.getXOffset() + infos[infoVariant].x * distantRenderer.getScaledWidth(),
|
||||||
|
y: distantRenderer.getYOffset() + infos[infoVariant].y * distantRenderer.getScaledHeight(),
|
||||||
|
width: infos[infoVariant].w * distantRenderer.getScaledWidth(),
|
||||||
|
height: infos[infoVariant].h * distantRenderer.getScaledHeight(),
|
||||||
|
visible: infos[infoVariant].w != 0 && infos[infoVariant].h != 0
|
||||||
|
})
|
||||||
|
if (!hover) {
|
||||||
|
console.log("Error when creating the hover")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hover.setParticipantName(infos[infoVariant].bestName)
|
||||||
|
hover.active = infos[infoVariant].active;
|
||||||
|
hover.isLocal = infos[infoVariant].isLocal;
|
||||||
|
hover.setMenuVisible(isMaster)
|
||||||
|
hover.uri = infos[infoVariant].uri
|
||||||
|
hover.injectedContextMenu = participantContextMenu
|
||||||
|
participantOverlays.push(hover)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
|
|
||||||
|
@ -313,10 +355,9 @@ Rectangle {
|
||||||
id: callOverlayRectMouseArea
|
id: callOverlayRectMouseArea
|
||||||
|
|
||||||
anchors.top: callOverlayRect.top
|
anchors.top: callOverlayRect.top
|
||||||
anchors.topMargin: 50
|
|
||||||
|
|
||||||
width: callOverlayRect.width
|
width: callOverlayRect.width
|
||||||
height: callOverlayRect.height - callOverlayButtonGroup.height - 50
|
height: callOverlayRect.height
|
||||||
|
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
propagateComposedEvents: true
|
propagateComposedEvents: true
|
||||||
|
@ -370,4 +411,8 @@ Rectangle {
|
||||||
ContactPickerCreation.openContactPicker()
|
ContactPickerCreation.openContactPicker()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParticipantContextMenu {
|
||||||
|
id: participantContextMenu
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,13 +34,24 @@ Rectangle {
|
||||||
* since no other methods can make buttons at the layout center.
|
* since no other methods can make buttons at the layout center.
|
||||||
*/
|
*/
|
||||||
property int buttonPreferredSize: 24
|
property int buttonPreferredSize: 24
|
||||||
|
property var isMaster: true
|
||||||
|
property var isSip: false
|
||||||
|
|
||||||
signal chatButtonClicked
|
signal chatButtonClicked
|
||||||
signal addToConferenceButtonClicked
|
signal addToConferenceButtonClicked
|
||||||
|
|
||||||
|
function updateMaster() {
|
||||||
|
root.isMaster = CallAdapter.isCurrentMaster()
|
||||||
|
addToConferenceButton.visible = !root.isSip && root.isMaster
|
||||||
|
}
|
||||||
|
|
||||||
function setButtonStatus(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall) {
|
function setButtonStatus(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall) {
|
||||||
|
root.isMaster = CallAdapter.isCurrentMaster()
|
||||||
|
root.isSip = isSIP
|
||||||
noVideoButton.visible = !isAudioOnly
|
noVideoButton.visible = !isAudioOnly
|
||||||
addToConferenceButton.visible = !isSIP
|
addToConferenceButton.visible = !isSIP && isMaster
|
||||||
|
transferCallButton.visible = isSIP
|
||||||
|
sipInputPanelButton.visible = isSIP
|
||||||
|
|
||||||
noMicButton.checked = isAudioMuted
|
noMicButton.checked = isAudioMuted
|
||||||
noVideoButton.checked = isVideoMuted
|
noVideoButton.checked = isVideoMuted
|
||||||
|
@ -148,6 +159,7 @@ Rectangle {
|
||||||
|
|
||||||
Layout.preferredWidth: buttonPreferredSize * 2
|
Layout.preferredWidth: buttonPreferredSize * 2
|
||||||
Layout.preferredHeight: buttonPreferredSize * 2
|
Layout.preferredHeight: buttonPreferredSize * 2
|
||||||
|
visible: !isMaster
|
||||||
|
|
||||||
backgroundColor: Qt.rgba(0, 0, 0, 0.75)
|
backgroundColor: Qt.rgba(0, 0, 0, 0.75)
|
||||||
onEnterColor: Qt.rgba(0, 0, 0, 0.6)
|
onEnterColor: Qt.rgba(0, 0, 0, 0.6)
|
||||||
|
|
|
@ -157,11 +157,17 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCallStatusChanged(status, accountId, convUid) {
|
function onCallStatusChanged(status, accountId, convUid) {
|
||||||
if (responsibleConvUid === convUid
|
if (responsibleConvUid === convUid && responsibleAccountId === accountId) {
|
||||||
&& responsibleAccountId === accountId) {
|
|
||||||
outgoingCallPage.callStatusPresentation = status
|
outgoingCallPage.callStatusPresentation = status
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onUpdateParticipantsInfos(infos, accountId, callId) {
|
||||||
|
var responsibleCallId = ClientWrapper.utilsAdaptor.getCallId(responsibleAccountId, responsibleConvUid)
|
||||||
|
if (responsibleCallId === callId) {
|
||||||
|
videoCallPage.handleParticipantsInfo(infos)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioCallPage {
|
AudioCallPage {
|
||||||
|
@ -198,6 +204,8 @@ Rectangle {
|
||||||
videoCallPage.parent = callStackMainView
|
videoCallPage.parent = callStackMainView
|
||||||
VideoCallFullScreenWindowContainerCreation.closeVideoCallFullScreenWindowContainer()
|
VideoCallFullScreenWindowContainerCreation.closeVideoCallFullScreenWindowContainer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
videoCallPage.handleParticipantsInfo(CallAdapter.getConferencesInfos())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
127
src/mainview/components/ParticipantContextMenu.qml
Normal file
127
src/mainview/components/ParticipantContextMenu.qml
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 by Savoir-faire Linux
|
||||||
|
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
import QtQuick 2.14
|
||||||
|
import QtQuick.Controls 2.14
|
||||||
|
import QtGraphicalEffects 1.12
|
||||||
|
import net.jami.Models 1.0
|
||||||
|
|
||||||
|
import "../../commoncomponents"
|
||||||
|
|
||||||
|
import "../js/videodevicecontextmenuitemcreation.js" as VideoDeviceContextMenuItemCreation
|
||||||
|
import "../js/selectscreenwindowcreation.js" as SelectScreenWindowCreation
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property int generalMenuSeparatorCount: 0
|
||||||
|
property int commonBorderWidth: 1
|
||||||
|
font.pointSize: JamiTheme.textFontSize + 3
|
||||||
|
property var uri: ""
|
||||||
|
property var maximized: true
|
||||||
|
property var active: true
|
||||||
|
|
||||||
|
function showHangup(show) {
|
||||||
|
if (show) {
|
||||||
|
hangupItem.visible = true
|
||||||
|
hangupItem.height = hangupItem.preferredHeight
|
||||||
|
} else {
|
||||||
|
hangupItem.visible = false
|
||||||
|
hangupItem.height = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showMaximize(show) {
|
||||||
|
if (show) {
|
||||||
|
maximizeItem.visible = true
|
||||||
|
maximizeItem.height = hangupItem.preferredHeight
|
||||||
|
} else {
|
||||||
|
maximizeItem.visible = false
|
||||||
|
maximizeItem.height = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showMinimize(show) {
|
||||||
|
if (show) {
|
||||||
|
minimizeItem.visible = true
|
||||||
|
minimizeItem.height = hangupItem.preferredHeight
|
||||||
|
} else {
|
||||||
|
minimizeItem.visible = false
|
||||||
|
minimizeItem.height = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setHeight(visibleItems) {
|
||||||
|
root.height = hangupItem.preferredHeight * visibleItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All GeneralMenuItems should remain the same width / height.
|
||||||
|
*/
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: hangupItem
|
||||||
|
|
||||||
|
itemName: qsTr("Hangup")
|
||||||
|
iconSource: "qrc:/images/icons/ic_call_end_white_24px.svg"
|
||||||
|
icon.color: "black"
|
||||||
|
leftBorderWidth: commonBorderWidth
|
||||||
|
rightBorderWidth: commonBorderWidth
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
CallAdapter.hangupCall(uri)
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: maximizeItem
|
||||||
|
|
||||||
|
itemName: qsTr("Maximize participant")
|
||||||
|
iconSource: "qrc:/images/icons/open_in_full-24px.svg"
|
||||||
|
leftBorderWidth: commonBorderWidth
|
||||||
|
rightBorderWidth: commonBorderWidth
|
||||||
|
visible: !maximized
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
CallAdapter.maximizeParticipant(uri, active)
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: minimizeItem
|
||||||
|
|
||||||
|
itemName: qsTr("Minimize participant")
|
||||||
|
iconSource: "qrc:/images/icons/close_fullscreen-24px.svg"
|
||||||
|
leftBorderWidth: commonBorderWidth
|
||||||
|
rightBorderWidth: commonBorderWidth
|
||||||
|
visible: maximized
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
CallAdapter.minimizeParticipant()
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
implicitWidth: hangupItem.preferredWidth
|
||||||
|
implicitHeight: hangupItem.preferredHeight * 3
|
||||||
|
|
||||||
|
border.width: commonBorderWidth
|
||||||
|
border.color: JamiTheme.tabbarBorderColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
169
src/mainview/components/ParticipantOverlay.qml
Normal file
169
src/mainview/components/ParticipantOverlay.qml
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 by Savoir-faire Linux
|
||||||
|
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
import QtQuick 2.14
|
||||||
|
import QtQuick.Controls 2.14
|
||||||
|
import QtQuick.Layouts 1.14
|
||||||
|
import QtQuick.Controls.Universal 2.12
|
||||||
|
import QtGraphicalEffects 1.14
|
||||||
|
import net.jami.Models 1.0
|
||||||
|
|
||||||
|
import "../../commoncomponents"
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property int buttonPreferredSize: 12
|
||||||
|
property var uri: ""
|
||||||
|
property var active: true
|
||||||
|
property var isLocal: true
|
||||||
|
property var injectedContextMenu: null
|
||||||
|
|
||||||
|
function setParticipantName(name) {
|
||||||
|
participantName.text = name
|
||||||
|
}
|
||||||
|
|
||||||
|
function setMenuVisible(isVisible) {
|
||||||
|
optionsButton.visible = isVisible
|
||||||
|
}
|
||||||
|
|
||||||
|
border.width: 1
|
||||||
|
opacity: 0
|
||||||
|
color: "transparent"
|
||||||
|
z: 1
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseAreaHover
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
propagateComposedEvents: true
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: bottomLabel
|
||||||
|
|
||||||
|
height: 24
|
||||||
|
width: parent.width
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
color: "black"
|
||||||
|
opacity: 0.8
|
||||||
|
height: parent.height
|
||||||
|
width: parent.width
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: parent.height
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: participantName
|
||||||
|
anchors.fill: parent
|
||||||
|
leftPadding: 8.0
|
||||||
|
|
||||||
|
TextMetrics {
|
||||||
|
id: participantMetrics
|
||||||
|
elide: Text.ElideRight
|
||||||
|
elideWidth: bottomLabel.width - 8
|
||||||
|
}
|
||||||
|
|
||||||
|
text: participantMetrics.elidedText
|
||||||
|
|
||||||
|
color: "white"
|
||||||
|
font.pointSize: JamiTheme.textFontSize
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: optionsButton
|
||||||
|
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: "transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
icon.color: "white"
|
||||||
|
icon.height: buttonPreferredSize
|
||||||
|
icon.width: buttonPreferredSize
|
||||||
|
icon.source: "qrc:/images/icons/more_vert-24px.svg"
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (!injectedContextMenu) {
|
||||||
|
console.log("Participant's overlay don't have any injected context menu")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var mousePos = mapToItem(videoCallPageRect, parent.x, parent.y)
|
||||||
|
var layout = CallAdapter.getCurrentLayoutType()
|
||||||
|
var showMaximized = layout !== 2
|
||||||
|
var showMinimized = !(layout === 0 || (layout === 1 && !active))
|
||||||
|
injectedContextMenu.showHangup(!root.isLocal)
|
||||||
|
injectedContextMenu.showMaximize(showMaximized)
|
||||||
|
injectedContextMenu.showMinimize(showMinimized)
|
||||||
|
injectedContextMenu.setHeight(
|
||||||
|
(root.isLocal ? 0 : 1)
|
||||||
|
+ (showMaximized ? 1 : 0)
|
||||||
|
+ (showMinimized ? 1 : 0))
|
||||||
|
injectedContextMenu.uri = uri
|
||||||
|
injectedContextMenu.active = active
|
||||||
|
injectedContextMenu.x = mousePos.x
|
||||||
|
injectedContextMenu.y = mousePos.y - injectedContextMenu.height
|
||||||
|
injectedContextMenu.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
CallAdapter.maximizeParticipant(uri, active)
|
||||||
|
}
|
||||||
|
|
||||||
|
onEntered: {
|
||||||
|
root.state = "entered"
|
||||||
|
}
|
||||||
|
|
||||||
|
onExited: {
|
||||||
|
root.state = "exited"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: "entered"
|
||||||
|
PropertyChanges {
|
||||||
|
target: root
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "exited"
|
||||||
|
PropertyChanges {
|
||||||
|
target: root
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
transitions: Transition {
|
||||||
|
PropertyAnimation {
|
||||||
|
target: root
|
||||||
|
property: "opacity"
|
||||||
|
duration: 500
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,6 +42,8 @@ Rectangle {
|
||||||
signal needToShowInFullScreen
|
signal needToShowInFullScreen
|
||||||
|
|
||||||
function updateUI(accountId, convUid) {
|
function updateUI(accountId, convUid) {
|
||||||
|
videoCallOverlay.handleParticipantsInfo(CallAdapter.getConferencesInfos())
|
||||||
|
|
||||||
bestName = ClientWrapper.utilsAdaptor.getBestName(accountId, convUid)
|
bestName = ClientWrapper.utilsAdaptor.getBestName(accountId, convUid)
|
||||||
|
|
||||||
var id = ClientWrapper.utilsAdaptor.getBestId(accountId, convUid)
|
var id = ClientWrapper.utilsAdaptor.getBestId(accountId, convUid)
|
||||||
|
@ -74,6 +76,15 @@ Rectangle {
|
||||||
videoCallOverlay.closePotentialContactPicker()
|
videoCallOverlay.closePotentialContactPicker()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleParticipantsInfo(infos) {
|
||||||
|
if (infos.length === 0) {
|
||||||
|
bestName = ClientWrapper.utilsAdaptor.getBestName(accountId, convUid)
|
||||||
|
} else {
|
||||||
|
bestName = ""
|
||||||
|
}
|
||||||
|
videoCallOverlay.handleParticipantsInfo(infos)
|
||||||
|
}
|
||||||
|
|
||||||
function previewMagneticSnap() {
|
function previewMagneticSnap() {
|
||||||
|
|
||||||
|
|
||||||
|
@ -225,6 +236,10 @@ Rectangle {
|
||||||
|
|
||||||
width: videoCallPageMainRect.width
|
width: videoCallPageMainRect.width
|
||||||
height: videoCallPageMainRect.height
|
height: videoCallPageMainRect.height
|
||||||
|
|
||||||
|
onOffsetChanged: {
|
||||||
|
videoCallOverlay.handleParticipantsInfo(CallAdapter.getConferencesInfos())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoCallPreviewRenderer {
|
VideoCallPreviewRenderer {
|
||||||
|
|
Loading…
Add table
Reference in a new issue